Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving certificate chain in a pkcs12 keystore

Tags:

The following code:

//used Bouncy Castle provider for keyStore keyStore.setKeyEntry(alias, (Key)keyPair.getPrivate(), pwd, certChain);   

where certChain holds the end certificate and the issuer certificate (i.e. two certificates),
doesn't save the issuer certificate as part of the chain in the saved to the file system keystore file if the keyStore is an instance of PKCS12.

It does save both certificates if the keystore type is PKCS12-3DES-3DES. Why is this? Doesn't a PKCS12 suppose to have both certificates are part of the chain?

EDIT: Here's an SSCCE. This works fine with "JKS", fails with "PKCS12": Only the first certificate in the chain is accessible via getCertificateChain(String). The saved file can be opened with openssl pkcs12 revealing both certificates.

    public void testKeyStore() {     try {         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");         keyPairGenerator.initialize(1024);         KeyPair keyPair = keyPairGenerator.generateKeyPair();         PublicKey publicKey = keyPair.getPublic();         PrivateKey privateKey = keyPair.getPrivate();         Certificate[] outChain = { createCertificate("CN=CA", publicKey, privateKey), createCertificate("CN=Client", publicKey, privateKey) };          KeyStore outStore = KeyStore.getInstance("PKCS12");         outStore.load(null, "secret".toCharArray());         outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain);                     OutputStream outputStream = new FileOutputStream("c:/outstore.pkcs12");         outStore.store(outputStream, "secret".toCharArray());         outputStream.flush();         outputStream.close();          KeyStore inStore = KeyStore.getInstance("PKCS12");               inStore.load(new FileInputStream("c:/outstore.pkcs12"), "secret".toCharArray());         Key key = outStore.getKey("myKey", "secret".toCharArray());         assertEquals(privateKey, key);          Certificate[] inChain = outStore.getCertificateChain("mykey");         assertNotNull(inChain);         assertEquals(outChain.length, inChain.length);     } catch (Exception e) {         e.printStackTrace();         fail(e.getMessage());     } }  private static X509Certificate createCertificate(String dn, PublicKey publicKey, PrivateKey privateKey) throws Exception {     X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();     certGenerator.setSerialNumber(new BigInteger("1"));     certGenerator.setIssuerDN(new X509Name(dn));     certGenerator.setSubjectDN(new X509Name(dn));     certGenerator.setNotBefore(Calendar.getInstance().getTime());     certGenerator.setNotAfter(Calendar.getInstance().getTime());     certGenerator.setPublicKey(publicKey);     certGenerator.setSignatureAlgorithm("SHA1withRSA");     X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC");     return certificate; } 
like image 520
Cratylus Avatar asked Nov 03 '12 08:11

Cratylus


People also ask

What is pkcs12 keystore format?

The PKCS#12 (Personal Information Exchange Syntax Standard) specifies a portable format for storage and/or transport of a user's private keys, certificates, miscellaneous secrets, and other items.

What is the difference between JKS and pkcs12?

The biggest difference between JKS and PKCS12 is that JKS is a format specific to Java, while PKCS12 is a standardized and language-neutral way of storing encrypted private keys and certificates.


1 Answers

Your code has 2 error:

first: You not set Issuer for certificate (client cert should be issued by CA to make valid chain).

second: You use wrong order when create certificate chain (should be client certs, CA last)

here is reworked SSCCE, and it works without errors.

@Test public void testKeyStore() throws Exception{         try {         String storeName =  "/home/grigory/outstore.pkcs12";         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");         keyPairGenerator.initialize(1024);         KeyPair keyPair = keyPairGenerator.generateKeyPair();         PublicKey publicKey = keyPair.getPublic();         PrivateKey privateKey = keyPair.getPrivate();         Certificate trustCert =  createCertificate("CN=CA", "CN=CA", publicKey, privateKey);         Certificate[] outChain = { createCertificate("CN=Client", "CN=CA", publicKey, privateKey), trustCert };          KeyStore outStore = KeyStore.getInstance("PKCS12");         outStore.load(null, "secret".toCharArray());         outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain);         OutputStream outputStream = new FileOutputStream(storeName);         outStore.store(outputStream, "secret".toCharArray());         outputStream.flush();         outputStream.close();          KeyStore inStore = KeyStore.getInstance("PKCS12");         inStore.load(new FileInputStream(storeName), "secret".toCharArray());         Key key = outStore.getKey("myKey", "secret".toCharArray());         Assert.assertEquals(privateKey, key);          Certificate[] inChain = outStore.getCertificateChain("mykey");         Assert.assertNotNull(inChain);         Assert.assertEquals(outChain.length, inChain.length);     } catch (Exception e) {         e.printStackTrace();         throw new AssertionError(e.getMessage());     }    }     private static X509Certificate createCertificate(String dn, String issuer, PublicKey publicKey, PrivateKey privateKey) throws Exception {         X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();         certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random().nextLong())));         certGenerator.setSubjectDN(new X509Name(dn));         certGenerator.setIssuerDN(new X509Name(issuer)); // Set issuer!         certGenerator.setNotBefore(Calendar.getInstance().getTime());         certGenerator.setNotAfter(Calendar.getInstance().getTime());         certGenerator.setPublicKey(publicKey);         certGenerator.setSignatureAlgorithm("SHA1withRSA");         X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC");         return certificate;     } 
like image 92
user1516873 Avatar answered Nov 18 '22 15:11

user1516873