Saving certificate chain in a pkcs12 keystore(将证书链保存在 pkcs12 密钥库中)
问题描述
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;
}
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;
}
这篇关于将证书链保存在 pkcs12 密钥库中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:将证书链保存在 pkcs12 密钥库中
基础教程推荐
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 在螺旋中写一个字符串 2022-01-01