Доступ к сертификатам Windows Certificate Store через Java?

Я пытаюсь написать что-то, что может перечислять и использовать (подписывать) сертификаты в CurrentUser/My и LocalMachine/My, но я не смог найти ничего для хранилища сертификатов Windows, только собственное секретное хранилище Java. Эта ссылка выглядит многообещающе, но я могу использовать только то, что поставляется с Java.

Я обнаружил, что этот вопрос задавался на SO раньше, но это было пять лет назад, что очень давно в компьютерные годы. Спасибо!

4 ответа

Запустите Java с -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT,

См. http://www.oracle.com/technetwork/articles/javase/security-137537.html для получения дополнительной информации.

Кроссплатформенная природа Java имеет свои недостатки: вы не можете получить доступ к некоторым (или многим) функциям, связанным с ОС, без внешних библиотек. Хранилище сертификатов Windows доступно только через собственные функции CryptoAPI, которые не поддерживаются установкой Java по умолчанию.

Вы можете взглянуть на эту тему: Вызов метода Win32 API из Java

Если вы можете использовать JNA, то вы можете использовать различные функции хранилища сертификатов и сертификатов в crypt32.dll для перечисления сертификатов и выполнения операций подписи.

KeyStore keyStore = KeyStore.getInstance(getKeyStoreType(), "SunMSCAPI");
keyStore.load(null, null);

try {
    Field field = keyStore.getClass().getDeclaredField("keyStoreSpi");
    field.setAccessible(true);

    KeyStoreSpi keyStoreVeritable = (KeyStoreSpi)field.get(keyStore);
    field = keyStoreVeritable.getClass().getEnclosingClass().getDeclaredField("entries");
    field.setAccessible(true);
} catch (Exception e) {
    LOGGER.log(Level.SEVERE, "Set accessible keyStoreSpi problem", e);
}

Enumeration enumeration = keyStore.aliases();

Я выбрал то место, где ушел Crypt32, и использовал JNA для доступа к сертификатам, используя тот же диалог Windows, который появляется, если вы должны использовать какую-либо специальную программу для Windows:

    NativeLibrary cryptUI = NativeLibrary.getInstance("Cryptui");
    NativeLibrary crypt32 = NativeLibrary.getInstance("Crypt32");

    Function functionCertOpenSystemStore = crypt32.getFunction("CertOpenSystemStoreA");
    Object[] argsCertOpenSystemStore = new Object[] { 0, "CA"};
    HANDLE h = (HANDLE) functionCertOpenSystemStore.invoke(HANDLE.class, argsCertOpenSystemStore);

    Function functionCryptUIDlgSelectCertificateFromStore = cryptUI.getFunction("CryptUIDlgSelectCertificateFromStore");
    System.out.println(functionCryptUIDlgSelectCertificateFromStore.getName());
    Object[] argsCryptUIDlgSelectCertificateFromStore = new Object[] { h, 0, 0, 0, 16, 0, 0};
    Pointer ptrCertContext = (Pointer) functionCryptUIDlgSelectCertificateFromStore.invoke(Pointer.class, argsCryptUIDlgSelectCertificateFromStore);

    Function functionCertGetNameString = crypt32.getFunction("CertGetNameStringW");
    char[] ptrName = new char[128];
    Object[] argsCertGetNameString = new Object[] { ptrCertContext, 5, 0, 0, ptrName, 128};
    functionCertGetNameString.invoke(argsCertGetNameString);
    System.out.println("Selected certificate is " + new String(ptrName));

    Function functionCertFreeCertificateContext = crypt32.getFunction("CertFreeCertificateContext");
    Object[] argsCertFreeCertificateContext = new Object[] { ptrCertContext};
    functionCertFreeCertificateContext.invoke(argsCertFreeCertificateContext);

    Function functionCertCloseStore = crypt32.getFunction("CertCloseStore");
    Object[] argsCertCloseStore = new Object[] { h, 0};
    functionCertCloseStore.invoke(argsCertCloseStore);

Это просто кусок кода, который работает; не стесняйтесь применять свои методы кодирования.

Другие вопросы по тегам