2012-03-14 33 views
14

Obtengo archivos externos .pem que deben convertirse a archivos .p12 - Añado un nombre de usuario y una contraseña en el proceso. (Necesito hacer esto para utilizar la API de una tercera parte.)Convierte SSL .pem a .p12 con o sin OpenSSL

Usando openssl, el comando es ...

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

puedo correr esto desde una sesión de terminal y funciona perfectamente.

Sin embargo, tendré que hacer esto a menudo y he escrito una clase de Java que maneja esto y más (mi aplicación es principalmente .jsp con Tomcat y Apache). Cuando intento ejecutar el mismo comando desde Java usando Runtime.exec, aparece el temido error "no se puede escribir 'estado aleatorio'" (Using OpenSSL what does "unable to write 'random state'" mean?).

Supongo que la diferencia es que, cuando corro desde Java, el usuario no es "root".

Entonces, ¿hay una forma mejor de convertir de pem a .p12 usando una biblioteca Java en lugar de ejecutar un programa de línea de comando (es decir, openssl)?

De lo contrario, supongo que necesito hacer alguna configuración en mi servidor. No puedo encontrar ningún archivo .md en ninguna parte del servidor. El único archivo openssl.cnf se encuentra en un directorio extraño (/etc/pki/tls). ¿Debo crear un nuevo archivo openssl.cnf en otro lugar?

Respuesta

0

En Java, use Bouncycastle, pero tenga cuidado, la curva de aprendizaje es empinada y la documentación escasa. Recomiendo encarecidamente que consulte los ejemplos que están disponibles como parte de la distribución fuente

Comience con el PemReader.

10

Esto debería hacer lo que quiera hacer (utilizando el BouncyCastle PEMReader como se sugirió anteriormente): tome un certificado + clave privada codificada en PEM, y envíe un archivo PKCS # 12. Utiliza la misma contraseña para el PKCS12 que se utilizó para proteger la clave privada.

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

Basado en respuesta @MugglesMerriweather 's, una versión actualizada a v1.51 es el siguiente:

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

'SC' significa proveedor de SpongyCastle. – EpicPandaForce

0

Sobre la base de las respuestas creé una clase Java 7, que se encarga de todo para la creación de una SSLContext válido También crea la cadena necesaria. TODO: Trustmanager si es necesario.

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

} 
Cuestiones relacionadas