未找到密钥保护算法:java.security.KeyStoreException:证书链未验证

时间:2017-10-13 23:03:50

标签: java

当我尝试创建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:证书链未验证。

我试着搜索这个,但没有找到太多信息。这是什么意思,或者我做错了什么?

2 个答案:

答案 0 :(得分:0)

我希望您执行以下步骤(假设jks文件的名称为abc.jks)

  1. 将abc.jks文件粘贴到java的bin文件夹中,其中存在keytool.exe文件(例如C:\ Program Files(x86)\ Java \ jre1.8.0_121 \ bin)
  2. 运行此命令keytool -keystore abc.jks -list -v并输入密码
  3. 现在您需要检查其中的以下内容    A.入门类型(它应该是私人的,如果不是,那么你没有钥匙)    B.证书链(如果是,则应为3,则需要导入CA证书)
  4. 您可以在图像中确认相同内容 enter image description here

    您可以使用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。