访问Java中的本地计算机证书存储?

访问Java中的本地计算机证书存储?,java,windows,tomcat,keystore,certificate-store,Java,Windows,Tomcat,Keystore,Certificate Store,是否可以从Javaservlet访问存储在本地计算机存储区而不是当前用户中的证书?我尝试使用MSCAPI提供程序打开Windows MY和Windows根存储,但它们都不包含来自本地计算机存储的证书。您要查找的证书位于java密钥库文件中,或者在启动服务器时传递到tomcat中 如果您试图将它们加载到应用程序中,请在此处查找以发出HTTPS请求,然后HTTPClient文档将帮助您开始 不确定这是否对你有帮助,但如果你能提供更多细节,那么你可能会得到更具体的答案 public class Key

是否可以从Javaservlet访问存储在本地计算机存储区而不是当前用户中的证书?我尝试使用MSCAPI提供程序打开Windows MY和Windows根存储,但它们都不包含来自本地计算机存储的证书。

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

如果您试图将它们加载到应用程序中,请在此处查找以发出HTTPS请求,然后HTTPClient文档将帮助您开始

不确定这是否对你有帮助,但如果你能提供更多细节,那么你可能会得到更具体的答案

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();
        }
    }
}

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

我使用JNA访问证书,使用与您使用任何windows特定程序时弹出的windows对话框相同的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);

它只是一段代码,可以工作;请随意应用您的编码实践。

正如其他人所提到的,MSCAPI提供程序不提供对本地计算机证书存储中存储的证书和密钥的访问。原因是MSCAPI使用Microsoft CryptoAPI函数CertOpenSystemStore访问证书和密钥。显式声明使用此方法只能访问当前用户证书,而不能访问本地计算机存储。如果您想跟踪此问题的进展,您可以进行跟踪

如果你想要一个适当的解决方案,你可以购买商业图书馆


如果你能忍受黑客攻击,我已经创建了一个拦截JDK对CertOpenSystemStore的调用并返回一个虚拟证书存储的句柄,允许对当前用户和本地机器证书存储中的证书和密钥进行只读访问。这解决了我的问题,但请注意此实用程序的局限性。

我不打算使用SSL。我想访问计算机证书并取出它们的密钥对以加密/解密配置文件中的某些设置。我已经使用当前用户的个人证书存储中的证书完成了这项操作,但是我想从本地计算机存储中提取SSL证书来进行加密。我只需要RSA密钥对。你是对的,我可以从当前用户的个人Windows MY store中获取密钥对,但我希望从本地计算机的个人证书存储中获取密钥对。我没有找到一种方法来指定要从哪个证书存储当前用户/本地计算机读取。它似乎只想从当前用户那里读取。我知道你想做什么,但是:为什么它要让你从其他用户的存储中读取?本地计算机的存储中是否有密钥对?-如果是这样,您的java进程将需要作为操作系统一部分的权限;你知道我如何授予java进程作为操作系统一部分的权限吗?这是java的难点之一,因为java.exe是二进制文件,如果我没记错的话,你必须授予它权限,而不是类文件。你的进程必须通过本机代码主动声明权限。我还应该提到,我正在猜测您将需要的操作系统权限。您能否先将一个受信任的证书(而不是密钥对)放入Windows根目录并检索它?是的,我可以从本地计算机Windows根目录存储检索证书。很好,本地计算机Windows我的存储对Java来说似乎是空的。您在这里实现了您想要的吗?我也遇到了同样的问题,一点运气都没有。@skw不,我从来都无法从纯Java检索本地计算机证书,我最终使用了Trust的提供程序,该提供程序执行JNI调用来检索我需要的证书。谢谢您的回复。可惜它不是Java本机的。我想这可能是一些安全问题。我如何使用这种方式获得私钥提供商?