用Java访问本地机器证书存储区?

时间:2010-08-31 20:28:55

标签: java windows tomcat keystore certificate-store

是否可以从Java Servlet访问存储在本地计算机存储(而不是当前用户)中的证书?我尝试使用MSCAPI提供程序打开“Windows-MY”和“Windows-ROOT”存储,但都不包含本地计算机存储中的证书。

4 个答案:

答案 0 :(得分:3)

我使用JNA使用相同的窗口对话框来访问证书,如果你要使用任何特定于Windows的程序,它会弹出 - 这可能无法解答你的问题,但肯定会让你提供一个选项来访问&#39 ; 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);

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

答案 1 :(得分:2)

默认的JDK实现相当有限。 AFAIK它只会带回RSA密钥和证书。它不是MSCAPI的通用适配器。我已经能够使用您描述的机制获得一些证书。

答案 2 :(得分:1)

正如其他人提到的那样,MSCAPI提供程序不提供对存储在“本地计算机”证书存储中的证书和密钥的访问。原因是MSCAPI使用Microsoft CryptoAPI函数CertOpenSystemStore访问证书和密钥。 documentation for this function明确指出“使用此方法只能访问当前用户证书,而不能访问本地计算机存储库”。如果您想跟踪此问题的进度,可以关注this OpenJDK bug

如果您想要适当的解决问题的方法,可以购买商业Pheox JCAPI库。

如果您可以接受黑客攻击,那么我创建了一个simple utility,它拦截了JDK对CertOpenSystemStore的调用,并将句柄返回到虚拟证书存储区,从而允许对证书和密钥的只读访问在“当前用户”和“本地计算机”证书存储中。这解决了我的问题,但请注意此实用程序的局限性。

答案 3 :(得分:-1)

您要查找的证书位于java密钥库文件中,或者在启动服务器时传递给tomcat

http://tomcat.apache.org/tomcat-4.0-doc/ssl-howto.html

如果您尝试在应用程序中加载它们,那么请查看此处以发出HTTPS请求,然后HTTPClient文档将帮助您入门

http://www.jdocs.com/httpclient/3.0.1/api-index.html?m=class&p=org.apache.commons.httpclient.contrib.ssl&c=AuthSSLProtocolSocketFactory&render=classic

不确定这是否会对您有所帮助,但如果您可以提供更多详细信息,那么您可以获得更具体的答案

public class KeyStoreLookup {
    public static void main(String args[]) {
        try {
            KeyStore ks = 
                      KeyStore.getInstance(KeyStore.getDefaultType());
            String fname = System.getProperty("user.home") +
                                File.separator + ".keystore";
            FileInputStream fis = new FileInputStream(fname);
            ks.load(fis, null);
            if (ks.isKeyEntry(args[0])) {
                System.out.println(args[0] +
                                " is a key entry in the keystore");
                char c[] = new char[args[1].length()];
                args[1].getChars(0, c.length, c, 0);
                System.out.println("The private key for" + args[0] + 
                            " is " + ks.getKey(args[0], c));
                Certificate certs[] = ks.getCertificateChain(args[0]);
                if (certs[0] instanceof X509Certificate) {
                    X509Certificate x509 = (X509Certificate) certs[0];
                    System.out.println(args[0] + " is really " +
                        x509.getSubjectDN());
                }
                if (certs[certs.length - 1] instanceof
                                     X509Certificate) {
                    X509Certificate x509 = (X509Certificate) 
                                        certs[certs.length - 1];
                    System.out.println(args[0] + " was verified by " +
                        x509.getIssuerDN());
                }
            }
            else if (ks.isCertificateEntry(args[0])) {
                System.out.println(args[0] +
                            " is a certificate entry in the keystore");
                Certificate c = ks.getCertificate(args[0]);
                if (c instanceof X509Certificate) {
                    X509Certificate x509 = (X509Certificate) c;
                    System.out.println(args[0] + " is really " +
                        x509.getSubjectDN());
                    System.out.println(args[0] + " was verified by " +
                        x509.getIssuerDN());
                }
            }
            else {
                System.out.println(args[0] +
                        " is unknown to this keystore");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
相关问题