将证书链保存在pkcs12密钥库中

以下代码:

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

certChain持有最终证书和颁发者证书(即两个证书),
如果keyStore是PKCS12的实例,则不会将颁发者证书保存为保存到文件系统密钥库文件中的链的一部分。

如果密钥库类型是PKCS12-3DES-3DES它会保存两个证书。 为什么是这样? PKCS12是否假设两个证书都是链的一部分?

编辑:这是一个SSCCE 。 这适用于"JKS" ,失败并显示"PKCS12" :只有链中的第一个证书可通过getCertificateChain(String)访问。 可以使用openssl pkcs12打开保存的文件,显示两个证书。

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

您的代码有2个错误:

第一:您没有为证书设置Issuer(CA应颁发客户端证书以生成有效链)。

第二:创建证书链时使用错误的顺序(应该是客户端ferts,CA last)

这里是重写SSCCE,它没有错误。

 @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.setIssuerDN(new X509Name(dn)); 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; } 

根据您使用的JDK,有不同的方法来打包您的应用程序。 当一些人使用Linux和OpenJDK以及其他一些使用SunJDK(Oracle)在Windows上开发时,会发生这种情况。

最新的有一些额外的配置要做,以便能够使用最强大的算法。 如果您的问题与JCE策略有关, 本文可以帮助您。