web-dev-qa-db-fra.com

Convertir SSL .pem en .p12 avec ou sans OpenSSL

Je reçois des fichiers .pem externes qui doivent être convertis en fichiers .p12. J'ajoute un nom d'utilisateur et un mot de passe au cours du processus. (Je dois le faire pour utiliser une API tierce.) 

En utilisant openssl, la commande est ...

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

Je peux l'exécuter depuis une session de terminal et cela fonctionne parfaitement. 

Cependant, je devrai le faire souvent et avoir écrit une classe Java qui gère cela et bien plus (mon application est principalement .jsp avec Tomcat et Apache). Lorsque j'essaie d'exécuter la même commande à partir de Java en utilisant Runtime.exec, j'obtiens l'erreur redoutée "impossible d'écrire" état aléatoire "" ( avec OpenSSL, que signifie "incapable d'écrire" état aléatoire "? ). 

Je suppose que la différence est que, lorsque je cours à partir de Java, l'utilisateur n'est pas "root". 

Alors, existe-t-il un meilleur moyen de convertir pem en .p12 à l’aide d’une bibliothèque Java plutôt que d’exécuter un programme en ligne de commande (par exemple, openssl)? 

Sinon, je suppose que je dois faire une configuration sur mon serveur. Je ne trouve aucun fichier .md sur le serveur. Le seul fichier openssl.cnf se trouve dans un répertoire étrange (/etc/pki/tls). Dois-je créer un nouveau fichier openssl.cnf ailleurs? 

15
DrDave

Cela devrait faire ce que vous voulez faire (en utilisant le PEMReader de BouncyCastle comme suggéré ci-dessus) - prenez une clé privée + un certificat codé par PEM et générez un fichier PKCS # 12. Utilise le même mot de passe pour le PKCS12 que celui utilisé pour protéger la clé privée.

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

En Java, utilisez Bouncycastle mais attention, la courbe d’apprentissage est raide et la documentation rare. Je vous recommande fortement de regarder les exemples disponibles dans le cadre de la distribution source

Commencez avec le PemReader.

1
Bruno Grieder

Selon la réponse de @MugglesMerriweather, une version mise à jour vers la v1.51 est la suivante:

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

Sur la base des réponses, j'ai créé une classe Java 7, qui gère tout pour créer un contexte SSLC valide. En outre, cela crée la chaîne nécessaire. TODO: Trustmanager si nécessaire.

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
sascha.arthur