Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert SSL .pem to .p12 with or without OpenSSL

Tags:

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?

like image 346
DrDave Avatar asked Mar 14 '12 22:03

DrDave


2 Answers

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();
}
like image 93
Muggles Merriweather Avatar answered Nov 09 '22 20:11

Muggles Merriweather


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();
    }
like image 35
EpicPandaForce Avatar answered Nov 09 '22 20:11

EpicPandaForce