使用或不使用OpenSSL将SSL .pem转换为.p12

我得到需要转换为.p12文件的外部.pem文件 – 我在此过程中添加了用户名和密码。 (我需要这样做才能使用第三方API。)

使用openssl ,命令是……

 openssl pkcs12 -export -in xxxx.pem -inkey xxxx.pem -out xxx.p12 -passout pas:newpassword -name "newname" 

我可以从终端会话运行它,它完美地工作。

但是,我需要经常这样做,并编写了一个Java类来处理这个和更多(我的应用程序主要是.jsp与Tomcat和Apache)。 当我尝试使用Runtime.exec从Java运行相同的命令时,我得到了可怕的“无法写入’随机状态’”错误( 使用OpenSSL“无法写入’随机状态’”是什么意思? )。

我假设不同之处在于,当我从Java运行时,用户不是“root”。

那么,是否有更好的方法使用Java库从pem转换为.p12而不是执行命令行程序(即openssl)?

否则,我想我需要在我的服务器上进行一些配置。 我在服务器上的任何地方都找不到任何.md文件。 唯一的openssl.cnf文件位于一个奇怪的目录( /etc/pki/tls )中。 我是否需要在其他地方创建一个新的openssl.cnf文件?

这应该做你想做的事情(使用上面建议的BouncyCastle PEMReader) – 获取PEM编码的私钥+证书,并输出PKCS#12文件。 使用用于保护私钥的PKCS12的相同密码。

 public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) throws Exception { // Get the private key FileReader reader = new FileReader(keyFile); PEMReader pem = new PEMReader(reader, new PasswordFinder() { @Override public char[] getPassword() { return password.toCharArray(); } }); PrivateKey key = ((KeyPair)pem.readObject()).getPrivate(); pem.close(); reader.close(); // Get the certificate reader = new FileReader(cerFile); pem = new PEMReader(reader); X509Certificate cert = (X509Certificate)pem.readObject(); pem.close(); reader.close(); // Put them into a PKCS12 keystore and write it to a byte[] ByteArrayOutputStream bos = new ByteArrayOutputStream(); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(null); ks.setKeyEntry("alias", (Key)key, password.toCharArray(), new java.security.cert.Certificate[]{cert}); ks.store(bos, password.toCharArray()); bos.close(); return bos.toByteArray(); } 

在Java中,使用Bouncycastle但要注意,学习曲线很陡,文档很少。 我强烈建议您查看作为源代码分发的一部分提供的示例

从PemReader开始。

根据@MugglesMerriweather的回答,v1.51的更新版本如下:

 public static byte[] convertPEMToPKCS12(final String keyFile, final String cerFile, final String password) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { // Get the private key FileReader reader = new FileReader(keyFile); PEMParser pem = new PEMParser(reader); PEMKeyPair pemKeyPair = ((PEMKeyPair)pem.readObject()); JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("SC"); KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair); PrivateKey key = keyPair.getPrivate(); pem.close(); reader.close(); // Get the certificate reader = new FileReader(cerFile); pem = new PEMParser(reader); X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject(); java.security.cert.Certificate X509Certificate = new JcaX509CertificateConverter().setProvider("SC") .getCertificate(certHolder); pem.close(); reader.close(); // Put them into a PKCS12 keystore and write it to a byte[] ByteArrayOutputStream bos = new ByteArrayOutputStream(); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(null); ks.setKeyEntry("alias", (Key) key, password.toCharArray(), new java.security.cert.Certificate[]{X509Certificate}); ks.store(bos, password.toCharArray()); bos.close(); return bos.toByteArray(); } 

根据答案,我创建了一个java 7类,它处理创建有效SSLContext的所有内容。 它还创造了必要的链条。 TODO:必要时为Trustmanager。

 public final class SSL_Context { private static SSL_Context instance = new SSL_Context(); public static SSL_Context getInstance() { return instance; } private SSLContext sslContext = null; private SSL_Context() { try { sslContext = generateSSLContext(); } catch (Exception e) { ErrorLogger.logException(e); } } final private void dumpKeyStore(KeyStore keyStore) { try { // List the aliases Enumeration aliases = keyStore.aliases(); for (; aliases.hasMoreElements(); ) { String alias = (String) aliases.nextElement(); // Does alias refer to a private key? boolean a = keyStore.isKeyEntry(alias); // Does alias refer to a trusted certificate? boolean b = keyStore.isCertificateEntry(alias); ErrorLogger.log(alias + " " + a + " " + b, 2); } } catch (Exception e) { ErrorLogger.logException(e); } } final private KeyStore convertPEMToPKCS12(final String keyAndPubFile, final String chainFile, final String password) { try { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); PrivateKey key; Certificate pubCert; try (FileReader reader = new FileReader(keyAndPubFile); PEMParser pem = new PEMParser(reader)) { PEMKeyPair pemKeyPair = ((PEMKeyPair) pem.readObject()); JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("BC"); KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair); key = keyPair.getPrivate(); X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject(); pubCert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder); } // Get the certificates try (FileReader reader = new FileReader(chainFile); PEMParser pem = new PEMParser(reader)) { //load all certs LinkedList certsll = new LinkedList<>(); X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject(); do { Certificate X509Certificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder); certsll.add(X509Certificate); } while ((certHolder = (X509CertificateHolder) pem.readObject()) != null); Certificate[] chain = new Certificate[certsll.size()+1]; chain[0] = pubCert; KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(null); int i = 1; for (Certificate cert : certsll) { ks.setCertificateEntry("chain" + i, cert); chain[i] = ks.getCertificate("chain" + i); i++; } ks.setKeyEntry("cert", key, password.toCharArray(), chain); return ks; } } catch (Exception e) { ErrorLogger.logException(e); } return null; } final private SSLContext generateSSLContext() { String keyStorePassword = ""; try { KeyStore keyStore = convertPEMToPKCS12("ssl/keyandcert.pem", "ssl/ca_bundle.crt", keyStorePassword); SSLContext sslContext = SSLContext.getInstance("TLSv1"); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom()); return sslContext; } catch (Exception e) { ErrorLogger.logException(e); } return null; } final public SSLContext getContext() { return sslContext; } final public static void main(String args[]) { getInstance().getContext(); } }