Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java access to intermediate CAs from Windows keystores?

I need to build a certificate chain on Windows, from an X.509 smart card cert through one or more intermediate CAs to a root CA. That's easy when the CA certs are in a JKS keystore, but I need to use the Windows keystores as well.

I can get the root CA cert from "Windows-ROOT", but I can't get to the "Intermediate Certification Authorities" keystore.

Has anyone done this?

Thanks!

like image 520
Mermeister Avatar asked Mar 29 '11 18:03

Mermeister


People also ask

Does Java use the Windows certificate store?

Instead of using the windows certificate store it uses its own implementation. Java certificates are stored in a file called cacerts located at C:\Program Files (x86)\Java\jre1. x.

How do I import a CA root certificate into the JVM trust store?

Import the certificate file into the JVM truststore using the following keytool command: $ keytool -importcert -alias [alias_of_certificate_entry] -file [path_to_certificate_file] -trustcacerts -keystore /path/to/truststore -storetype [storetype]

How do I view cacerts certificates?

To view the entries in a cacerts file, you can use the keytool utility provided with Sun J2SDK versions 1.4 or later. The following example uses the -list command to display the CA certificates in the cacerts file.


2 Answers

The SunMSCAPI Cryptographic provider does only support two keystores: Windows-MY (personal certificate store) and Windows-ROOT (trusted authorities certificate store), thus I don't thinks it is possible to directly access to other windows certificate stores. However it may not be necessart since it seems that the Windows-MY keystore is able to build certificate chains with the certificates from other stores.

Here is a code snippet I use to test it:

KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null) ;
Enumeration en = ks.aliases() ;
while (en.hasMoreElements()) {
    String aliasKey = (String)en.nextElement() ;
    Certificate c = ks.getCertificate(aliasKey) ;
    System.out.println("---> alias : " + aliasKey) ;
    if (ks.isKeyEntry(aliasKey)) {
        Certificate[] chain = ks.getCertificateChain(aliasKey);
        System.out.println("---> chain length: " + chain.length);
        for (Certificate cert: chain) {
            System.out.println(cert);
    }
}

If I add a single certificate with private key in the personal certificate store the chain length is 1. After adding the CA in the intermediate CA certificate store the I launch the program a second time and the chain length is now 2.

UPDATE (April, 2nd) It is possible to programmatically add certificates in the Windows-MY and Windows-ROOT keystore with some limitations:

  • when adding a certificate in the Windows-ROOT the user is prompted for confirmation
  • all certificate added in the Windows-MY keystore is a TrustedCertificateEntry (from the keystore point of view, not the Windows point of view). The keystore seems to build the longest possible chain with all available certificates.
  • the certifcates with no associated private key are not visible in the Windows certificate store browser but it is possible to programmatically delete them.

Adding a certificate in a keystore is straightforward:

Certificate c = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream("C:/Users/me/Downloads/myca.crt"));
KeyStore.TrustedCertificateEntry entry = new KeyStore.TrustedCertificateEntry(c);
ks.setEntry("CA1", entry , null);
like image 183
Jcs Avatar answered Oct 05 '22 07:10

Jcs


Jcs had the answer, but I want to show some pseudocode so:

// load the Windows keystore
KeyStore winKeystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
winKeystore.load(null, null);

// add the user's smart card cert to the keystore
winKeystore.setCertificateEntry(myAlias, userCertificate);

// build the cert chain! this will include intermediate CAs
Certificate[] chain = winKeystore.getCertificateChain(myAlias);

Windows cert chains aren't validated as they're built, but now you can do the usual thing of creating a CertPath and PKIXParameters and using them to validate the chain.

CertPathValidator certPathValidator = CertPathValidator.getInstance(CertPathValidator.getDefaultType());
certPathValidator.validate(certPath, params);
like image 28
Mermeister Avatar answered Oct 05 '22 06:10

Mermeister