Convert SSL .pem to .p12 with or without OpenSSL

匿名 (未验证) 提交于 2019-12-03 02:45:02

问题:

I get external .pem files that need to be converted to .p12 files - I add a username and password in the process. (I need to do this to utilize a third party API.)

Using openssl, the command is...

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

I can run this from a terminal session and it works perfectly.

However, I will need to do this often and have written a Java class that handles this and more (my application is mostly .jsp with Tomcat and Apache). When I try run the same command from Java using Runtime.exec, I get the dreaded "unable to write 'random state'" error ( Using OpenSSL what does "unable to write 'random state'" mean? ).

I assume that the difference is that, when I run from Java, the user is not "root".

So, is there a better way to convert from pem to .p12 using a Java library rather than executing a command line program (i.e. openssl)?

Otherwise, I guess I need to do some configuration on my server. I can not find any .md file anywhere on the server. The only openssl.cnf file is in a weird directory (/etc/pki/tls). Do I need to create a new openssl.cnf file somewhere else?

回答1:

This should do what you want to do (using the BouncyCastle PEMReader as suggested above) -- take a PEM-encoded private key + certificate, and output a PKCS#12 file. Uses the same password for the PKCS12 that was used to protect the private key.

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(); } 


回答2:

In Java, use Bouncycastle but be warned, learning curve is steep and documentation scarce. I strongly recommend you look at the examples which are available as part of the source distribution

Start with the PemReader.



回答3:

Based on @MugglesMerriweather 's answer, an updated version to v1.51 is the following:

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();     } 


回答4:

Based on the answers i created a java 7 class, which handles everything for creating a valid SSLContext. Also it creates the necessary chain. TODO: Trustmanager if necessary.

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<Certificate> 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(); }  } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!