17

I need asymmetric encryption in java. I generate .key and .crt files with own password and .crt file by openssl that said in http://www.imacat.idv.tw/tech/sslcerts.html .
How to use these .key and .crt file to extract publickey and private key in Java?

Sajad Bahmani
  • 16,531
  • 27
  • 81
  • 105

4 Answers4

26

Your .key and .crt files may be in PEM format. To check this open them with a text editor and check whether the content looks like ------BEGIN CERTIFICATE------ (or "begin RSA private key"...). This is generally the default format used by OpenSSL, unless you've explicitly specified DER.

It's probably not required (see below), but if your certificate is in DER format (a binary format), you can convert them in PEM format using:

openssl x509 -inform DER -in cert.crt -outform PEM -out cert.pem

(Check the help for openssl rsa for doing something similar with the private key if needed.)

You then get two options:

  • Build a PKCS#12 file

    openssl pkcs12 -export -in myhost.crt -inkey myhost.key -out myhost.p12
    

You can then use it directly from Java as a keystore of type "PKCS12". Most Java applications should allow you to specify a keystore type in addition to the file location. For the default system properties, this is done with javax.net.ssl.keyStoreType (but the application you're using might not be using this). Otherwise, if you want to load it explicitly, use something like this:

KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis =
    new FileInputStream("/path/to/myhost.p12");
ks.load(fis, "password".toCharArray()); // There are other ways to read the password.
fis.close();

(Then, you should be able to iterate through the aliases() of the KeyStore and use getCertificate (and then getPublicKey() for the public key) and getKey().

  • Use BouncyCastle's PEMReader.

     FileReader fr = ... // Create a FileReader for myhost.crt
     PEMReader pemReader = new PEMReader(fr);
     X509Certificate cert = (X509Certificate)pemReader.readObject();
     PublicKey pk = cert.getPublicKey();
     // Close reader...
    

For the private key, you'll need to implement a PasswordFinder (see link from PEMReader doc) for constructing the PEMReader if the private key is password-protected. (You'll need to cast the result of readObject() into a Key or PrivateKey.)

Bruno
  • 110,518
  • 24
  • 258
  • 357
  • how to get private key with ks ? – Sajad Bahmani Jun 27 '11 at 08:37
  • Using `getKey()`. When using the PKCS#12 format, it's the same password for the key as for the store itself. – Bruno Jun 27 '11 at 08:40
  • Thank you so much for this little example. It helped me understand the pem-reader, read the .crt files I have, understand DER/PEM a little better, etc. Now there shouldn't be a problem getting both keys out of the pem file. Can you just go write for bouncycastle... they need help! – Andrew Backer Jul 21 '14 at 09:39
  • 2
    @AndrewBacker, just remembered that BouncyCastle's `PEMReader` is not always necessary, depending on what you have to read. If it's just for certificates, you can try the `CertificateFactory` (part of JSSE). See example [here](http://stackoverflow.com/a/18514628/372643) and note [here](http://stackoverflow.com/a/14561932/372643) (the comment might be useful there). – Bruno Jul 21 '14 at 09:46
  • Yep. I do have PEM encoded files so the `CertificateFactory` seems to work... but `generateCertificate` for the name... wouldn't have guessed in a year. – Andrew Backer Jul 21 '14 at 10:08
  • @AndrewBacker, you don't have to guess, you just have to [read the doc](http://docs.oracle.com/javase/7/docs/api/java/security/cert/CertificateFactory.html) ;-) – Bruno Jul 21 '14 at 10:10
  • @Bruno True, in a way. Now that I know it is right, and what it does, I can understand that doc. But I would never have _found_ it on my own :D So thanks again... BTW... the _dreck_ they write ("use generateCertificates when you want to parse a collection of possibly unrelated certificates"? but I have one .crt file, not an unrelated collection? Is 1 file a collection? Is that a .pem with 2 certs? Hm... know you are the sec guy, so it's all obvious. But I bet not from reading the docs! – Andrew Backer Jul 22 '14 at 03:08
4

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

Take a look at org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator

Kirby
  • 13,024
  • 6
  • 79
  • 95
1

As I understand it, OpenSSL has saved files in so-called PEM format. You need to convert it to Java Key Storage (JKS) format, then work with that format (which is native to Java) to extract files. For conversion please use this Google query, it gives pretty good results.

Load the JKS file to java.security.KeyStore class. Then use getCertificate and getKey methods to get the needed information.

Eugene Mayevski 'Callback
  • 43,492
  • 7
  • 62
  • 119