当我尝试创建JKS文件,将其写入磁盘,然后运行keytool将其转换为P12时,我收到此错误。我之所以选择这条路是因为我无法在代码中获得适用于iOS的P12(不是加密人)。有足够的代码来创建JKS。要创建我的结束凭证,我这样做:
public X509Certificate buildEndEntityCert(PublicKey entityKey, PrivateKey caKey, X509Certificate caCert, String clientName)
throws Exception {
String name = "CN=" + clientName;
X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder(
caCert.getSubjectX500Principal(),
BigInteger.ONE,
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis() + VALIDITY_PERIOD),
new X500Principal(name),
entityKey);
JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(caCert))
.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(entityKey))
.addExtension(Extension.basicConstraints, false, new BasicConstraints(false))
.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.nonRepudiation))
.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth));
ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(caKey);
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certBldr.build(signer));
}
我调用该方法并像这样创建JKS:
KeyPair endPair = generateRSAKeyPair(2048);
X509Certificate endCert = buildEndEntityCert(endPair.getPublic(), intermediateCredential.getPrivateKey(), intermediateCredential.getCertificate(), clientName); // intermediateCredential and rootCredential are properties of this class that get loaded when the app starts up
X500PrivateCredential endCredential = new X500PrivateCredential(endCert, endPair.getPrivate(), clientName);
KeyStore store = KeyStore.getInstance("JKS");
store.load(null, null);
store.setKeyEntry(clientName, endCredential.getPrivateKey(), "secret".toCharArray(),
new Certificate[]{
endCredential.getCertificate(),
intermediateCredential.getCertificate(),
rootCredential.getCertificate()
});
store.store(new FileOutputStream(clientName + ".jks"), "secret".toCharArray());
然后当我从ProcessBuilder运行keytool时:
"C:\\Program Files\\Java\\jdk1.7.0_80\\bin\\keytool",
"-importkeystore",
"-srckeystore",
clientName + ".jks",
"-destkeystore",
clientName + ".p12",
"-srcstoretype", "JKS",
"-deststoretype", "PKCS12",
"-deststorepass",
clientName,
"-srcalias",
clientName,
"-destalias",
clientName
我明白了:
导入别名CLIENT_NAME的条目时出现问题:java.security.KeyStoreException:找不到密钥保护算法:java.security.KeyStoreException:证书链未验证。
我试着搜索这个,但没有找到太多信息。这是什么意思,或者我做错了什么?
答案 0 :(得分:0)
我希望您执行以下步骤(假设jks文件的名称为abc.jks)
keytool -keystore abc.jks -list -v
并输入密码您可以使用this命令将jks转换为pfx keytool -importkeystore -srckeystore abc.jks -srcstoretype jks -destkeystore xyz.pfx -deststoretype pkcs12
(我建议将abc.jks粘贴到java的bin文件夹中)您需要将扩展名更改为P12 强>
答案 1 :(得分:0)
我有同样的例外,尝试以编程方式填写密钥库。
我将问题追溯到sun.security.pkcs12.PKCS12KeyStore
方法setKeyEntry
if (chain != null) {
// validate cert-chain
if ((chain.length > 1) && (!validateChain(chain)))
throw new KeyStoreException("Certificate chain is " +
"not valid");
方法validateChain
private boolean validateChain(Certificate[] certChain)
{
for (int i = 0; i < certChain.length-1; i++) {
X500Principal issuerDN =
((X509Certificate)certChain[i]).getIssuerX500Principal();
X500Principal subjectDN =
((X509Certificate)certChain[i+1]).getSubjectX500Principal();
if (!(issuerDN.equals(subjectDN)))
return false;
}
// Check for loops in the chain. If there are repeated certs,
// the Set of certs in the chain will contain fewer certs than
// the chain
Set<Certificate> set = new HashSet<>(Arrays.asList(certChain));
return set.size() == certChain.length;
}
请检查intermediateCredential和rootCredential。