Доступ к сертификатам 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);
Это просто кусок кода, который работает; не стесняйтесь применять свои методы кодирования.