开发者

Access Local Machine Certificate Store in Java?

开发者 https://www.devze.com 2023-01-14 20:28 出处:网络
Is it possible to access certificates stored in the Local Machine store (rather than Current User) from a Java Servlet? I\'ve tried using the MSCAPI provider ope开发者_开发技巧ning the \"Windows-MY\"

Is it possible to access certificates stored in the Local Machine store (rather than Current User) from a Java Servlet? I've tried using the MSCAPI provider ope开发者_开发技巧ning the "Windows-MY" and "Windows-ROOT" stores, but neither contain certificates from the Local Machine store.


I used used JNA to access the certificates using the same windows dialog that pops up if you were to use any windows specific program - this may not answer your question but certainly lets you provide an option to access anything in a 'windows way':

    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.


The default JDK implementation is fairly limited. AFAIK it will only bring back RSA keys and certificates. It is not a general purpose adapter to MSCAPI. I have been able to get some certs back using the mechanism you describe.


As others have mentioned, the MSCAPI provider does not provide access to certificates and keys stored in the "Local Computer" certificate store. The reason for this is that MSCAPI uses the Microsoft CryptoAPI function CertOpenSystemStore to access the certificates and keys. The documentation for this function explicitly states that "Only current user certificates are accessible using this method, not the local machine store". You can follow this OpenJDK bug if you want to track progress on this issue.

If you want a proper solution to the problem you can purchase the commercial Pheox JCAPI library.

If you can live with a hack, I have created a simple utility that intercepts the JDKs call to CertOpenSystemStore and returns a handle to a virtual certificate store allowing read-only access to the certificates and keys in both the "Current User" and "Local Machine" certificate stores. This solved my problem, but be aware of the limitations of this utility.


The certificates you are looking for are in the java keystore file or are passed into tomcat when starting the server

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

if you are trying to load them in your application, then look here for to make HTTPS requests, then the HTTPClient documentation will get you started

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

not sure if this helps you out, but if you can provide more details, then you might be able to get a more specific answer

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

精彩评论

暂无评论...
验证码 换一张
取 消