2015-12-08 58 views
1

我正在寻找能够枚举和使用(签名)CurrentUser/My和LocalMachine/My中的证书的东西,但是我一直无法找到Windows证书存储区的任何内容,只有Java自己的秘密存储区。 This link看起来很有希望,但我只能使用Java附带的东西。通过Java访问Windows证书存储证书?

我发现this question之前被问过,但它是从五年前开始的,这在计算机年代已经很长时间了。谢谢!

回答

1

Java的跨平台性质有它自己的缺点 - 你不能访问一些(或许多)特定于操作系统的东西,而无需外部库。 Windows证书存储只能通过Java缺省安装不支持的CryptoAPI本机函数访问。

你可以看看这个线程:Calling Win32 API method from Java

如果你可以使用JNA,那么您可以使用各种Certificate and Certificate Store Functions在crypt32.dll枚举证书和执行签名操作。

+0

JNA听起来像是一个不错的选择......但我无法理解那里的示例代码。我不认为你知道任何C#/ .NET的方法吗? – Benjin

+0

我希望微软通过允许非Windows Java通过组策略更新来读取Windows服务器推送的信任存储,从而表达了良好的愿望。例如。提供从域服务器下载的PEM包:-) –

0
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(); 
+0

这是如何确定它正在枚举的Windows证书存储区内的哪个路径?我期望在某处看到“LocalMachine”或“CurrentUser”。 – Benjin

+0

我想,你不能得到这个信息。但是,也许我错了。让我知道什么时候你会想出这个。 – Krzysiek

0

我从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); 

它只是一块有效的代码;随时应用您的编码实践。