Convert SSL .pem to .p12 with or without OpenSSL

后端 未结 5 558
盖世英雄少女心
盖世英雄少女心 2021-01-30 23:18

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 thir

相关标签:
5条回答
  • 2021-01-30 23:57

    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();
    }
    
    0 讨论(0)
  • 2021-01-31 00:01

    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();
    }
    
    }
    
    0 讨论(0)
  • 2021-01-31 00:01

    This solutions is an adaptation of @sascha-arthur's to accomodate for:

    • Handles edge-case where PrivateKey format is not as expected.
    • Gracefully handle scenario where public key is not available
    • Fixed a few minor redundancies and formatting

    The code:

    String alias="myalias";
    char[] password = "mypassword".toCharArray();
    
    // Private Key
    PEMParser pem = new PEMParser(new FileReader(keyFile));
    Object parsedObject = pem.readObject();
    
    PrivateKeyInfo privateKeyInfo = parsedObject instanceof PEMKeyPair ? ((PEMKeyPair)parsedObject).getPrivateKeyInfo() : (PrivateKeyInfo)parsedObject;
    PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
    KeyFactory factory = KeyFactory.getInstance("RSA");
    PrivateKey key = factory.generatePrivate(privateKeySpec);
    
    List<X509Certificate> certs = new ArrayList<>();
    X509CertificateHolder certHolder = (X509CertificateHolder)pem.readObject();
    if(certHolder != null) {
        certs.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder));
    }
    
    // Certificate
    pem = new PEMParser(new FileReader(certFile));
    while((certHolder = (X509CertificateHolder)pem.readObject()) != null) {
        certs.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder));
    }
    
    // Keystore
    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(null);
    
    for (int i = 0; i < certs.size(); i++) {
        ks.setCertificateEntry(alias + "_" + i, certs.get(i));
    }
    
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(null);
    keyStore.setKeyEntry(alias, key, password, certs.toArray(new X509Certificate[certs.size()]));
    

    For this to work with a LetsEncrypt certificate, you'll need to use the following files:

    • privkey.pem
    • fullchain.pem
    0 讨论(0)
  • 2021-01-31 00:07

    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.

    0 讨论(0)
  • 2021-01-31 00:20

    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();
        }
    
    0 讨论(0)
提交回复
热议问题