I'm looking to write something that can enumerate and use (to sign) certificates in CurrentUser/My and LocalMachine/My, but I haven't been able to find anything for the Windows cert store, only Java's own secret store. This link looks promising, but I can only use what ships with Java.
I found this question asked on SO before, but it's from five years ago, which is a long time in computer years. Thanks!
Start Java with -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT
.
See http://www.oracle.com/technetwork/articles/javase/security-137537.html for more information.
The cross-platform nature of the Java has its own downsides -- you cannot access some (or many) OS-specific things without external libraries. Windows certificate store is accessible only via CryptoAPI native functions which are not support by Java default installation.
You may take a look at this thread: Calling Win32 API method from Java
If you can use JNA, then you can use various Certificate and Certificate Store Functions in crypt32.dll to enumerate certificates and perform signing operations.
I picked from where Crypt32 left, used JNA to access the certificates using the same windows dialog that pops up if you were to use any windows specific program:
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);
It is just a piece of code that works; feel free to apply your coding practices.
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();
来源:https://stackoverflow.com/questions/34166304/accessing-windows-certificate-store-certs-via-java