2012-03-14 20 views
14

Tôi nhận các tệp bên ngoài .pem cần được chuyển đổi thành .p12 tệp - Tôi thêm tên người dùng và mật khẩu trong quy trình. (Tôi cần phải làm điều này để sử dụng một API của bên thứ ba.)Chuyển đổi SSL .pem thành .p12 có hoặc không có OpenSSL

Sử dụng openssl, lệnh là ...

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

tôi có thể chạy này từ một phiên Terminal và nó hoạt động hoàn hảo.

Tuy nhiên, tôi sẽ cần phải làm điều này thường xuyên và đã viết một lớp Java xử lý việc này và hơn thế nữa (ứng dụng của tôi chủ yếu là .jsp với Tomcat và Apache). Khi tôi thử chạy lệnh tương tự từ Java sử dụng Runtime.exec, tôi nhận được lỗi "không thể ghi" trạng thái ngẫu nhiên "đáng sợ" (Using OpenSSL what does "unable to write 'random state'" mean?).

Tôi giả sử rằng sự khác biệt là khi tôi chạy từ Java, người dùng không phải là "gốc".

Vì vậy, có cách nào tốt hơn để chuyển đổi từ pem sang .p12 bằng cách sử dụng thư viện Java thay vì thực thi chương trình dòng lệnh (tức là openssl) không?

Nếu không, tôi đoán tôi cần thực hiện một số cấu hình trên máy chủ của mình. Tôi không thể tìm thấy bất kỳ tập tin .md ở bất cứ đâu trên máy chủ. Tệp openssl.cnf chỉ có trong một thư mục lạ (/etc/pki/tls). Tôi có cần tạo một tệp openssl.cnf mới ở một nơi khác không?

Trả lời

0

Trong Java, sử dụng Bouncycastle nhưng được cảnh báo, đường cong học tập dốc và tài liệu khan hiếm. Tôi đặc biệt khuyên bạn nên xem các ví dụ có sẵn như là một phần của bản phân phối nguồn

Bắt đầu với PemReader.

10

Điều này sẽ làm những gì bạn muốn làm (sử dụng PEMReader BouncyCastle như đã đề xuất ở trên) - lấy chứng chỉ khóa + mã hóa riêng PEM và xuất tệp PKCS # 12. Sử dụng cùng một mật khẩu cho PKCS12 được sử dụng để bảo vệ khóa riêng tư.

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

Dựa trên câu trả lời @MugglesMerriweather 's, một phiên bản cập nhật để v1.51 như sau:

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' là viết tắt của nhà cung cấp SpongyCastle. – EpicPandaForce

0

Dựa trên câu trả lời tôi đã tạo ra một lớp java 7, mà xử lý tất cả mọi thứ để tạo một SSLContext hợp lệ. Ngoài ra nó tạo ra các chuỗi cần thiết. TODO: Trustmanager nếu cần thiết.

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

}