18

我正在寻找可以在 CurrentUser/My 和 LocalMachine/My 中枚举和使用(签名)证书的东西,但我无法找到 Windows 证书存储区的任何东西,只有 Java 自己的秘密存储区。 这个链接看起来很有希望,但我只能使用 Java 附带的内容。

我发现这个问题以前在 SO 上问过,但它是从五年前开始的,这在计算机时代已经很长一段时间了。谢谢!

4

4 回答 4

27

-Djavax.net.ssl.trustStoreType=WINDOWS-ROOT.

有关详细信息,请参阅https://www.oracle.com/technical-resources/articles/javase/security.html

于 2018-09-14T10:59:50.910 回答
1

我从 Crypt32 离开的地方选择,使用 JNA 访问证书,使用相同的窗口对话框,如果您要使用任何特定于 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);

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

于 2017-02-07T11:20:46.063 回答
1

Java 的跨平台特性有其自身的缺点——如果没有外部库,您将无法访问某些(或许多)特定于操作系统的东西。Windows 证书存储只能通过 Java 默认安装不支持的 CryptoAPI 本机函数访问。

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

如果您可以使用 JNA,那么您可以使用 crypt32.dll 中的各种证书和证书存储函数来枚举证书并执行签名操作。

于 2015-12-09T09:20:31.163 回答
1
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();
于 2015-12-09T09:24:02.510 回答