由于错误而使用Java API错误创建pkcs12:java.security.KeyStoreException:不支持TrustedCertEntry

时间:2014-11-26 22:46:26

标签: java ssl keytool pkcs#12

我正在尝试使用Java API创建PKCS12密钥库文件。但是,只要我尝试导入证书,我就会得到异常

java.security.KeyStoreException: TrustedCertEntry not supported

我的代码是:

Provider p = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
...
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, keystorePass);

keyStore.setCertificateEntry("certificate", certificate);

keyStore.setKeyEntry("key",privateKey, keypass, certChain);

相同的方法适用于创建JKS文件但对于PKCS12文件失败。

注意: 作为输入提供给该程序的证书由服务器使用使用此处使用的相同私钥生成的CSR创建。即给定证书的公共模数,用于生成它的CSR和给定的私钥是相同的。

服务器证书存储在变量certChain中。

注意: 我已经尝试过OpenSSL来创建pkcs12并且我很成功,但是我需要使用Java API来做同样的事情。

注意:我使用的是JDK 7

2 个答案:

答案 0 :(得分:8)

Java 7(及更早版本)不允许在PKCS12密钥库中使用trustedCert条目,尽管8可能,因为PKCS12是设计的,通常仅用于私钥和相关的证书和哪个Java放在privateKey条目中。您说此证书是/匹配私钥的证书,因此必须首先在“密钥”条目的certChain中,并且需要“证书” “进入它。

答案 1 :(得分:0)

如Dave Thompson所报告的,我们不能使用Java 7(及更低版本),因为它不允许PKCS12中的trustCert条目。

如果您仍然坚持使用Java 7(或更早版本),则以下内容将有所帮助(注意:我使用BouncyCastle来获得TLS1.2支持):

X509Certificate ca = (X509Certificate) CertificateFactory.getInstance("X.509")
    .generateCertificate(new ByteArrayInputStream(cert.getBytes()));
            
KeyStore ts = KeyStore.getInstance("JKS");
KeyStore ks = KeyStore.getInstance("PKCS12");
                        
ts.load(null, null);
ks.load(null, null);
            
ts.setCertificateEntry("certAlias", ca);
        
PrivateKey privateKey = null;
PemReader pemReader = new PemReader(
    new InputStreamReader(new ByteArrayInputStream(key.getBytes())));
    
try {
    PemObject pemObject = pemReader.readPemObject();
    KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
    byte[] content = pemObject.getContent();
    PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
    privateKey = factory.generatePrivate(privKeySpec);
} finally {
    pemReader.close();
}
ks.setKeyEntry("keyAlias", privateKey, keyPassword, new X509Certificate[] { ca });
        
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
        
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keyPassword);
        
SSLContext sslContext = SSLContext.getInstance("TLS", BouncyCastleJsseProvider.PROVIDER_NAME);
sslContext.init(kmf.getKeyManagers(), trustManagers,
        SecureRandom.getInstance("DEFAULT", BouncyCastleProvider.PROVIDER_NAME));

注意:在上述代码中: 变量 cert 是证书的字符串内容,其开头为: ----- BEGIN CERTIFICATE ----- \ n

变量密钥是基于pem的私有密钥的字符串内容,其开头为: ----- BEGIN私有密钥----- \ n < / p>

变量 keyPassword 是密钥库密码的字符串内容。

以下是上述代码的一些Java导入,以提供清晰的信息:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
    
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
    
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;