Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate RSA Private key from *pem string in Java

I want to generate the private key from a string(a .pem file) in Java.

private static final String test = "-----BEGIN RSA PRIVATE KEY-----\n" +
         "MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" +
// and so on
         "-----END RSA PRIVATE KEY-----";

try {
    String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

    byte [] encoded = Base64.decode(privKeyPEM);

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey privKey = kf.generatePrivate(keySpec);
}
catch (Exception e) {
    e.printStackTrace();
}

The last line(generatePrivate function) is throwing this exception:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
    at java.security.KeyFactory.generatePrivate(Unknown Source)
    at Test.main(Test.java:52)
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
    at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
    at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source)
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source)
    at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source)
    ... 3 more

If I change the private key to the value from a .der file it works properly, but I need to generate the private key file from a .pem file.

I attached a screenshot of the bytes printed as string(once hard-coded with \n and once hard-coded without \n) and once from the file.

Bigger Image

Output

The weird thing is that the output from the file is different to the output from the strings.

If I try to encode a .der file with Base64, the result is different than the string in the .pem file. Why is that so?

like image 460
Niklas Avatar asked Aug 21 '13 23:08

Niklas


People also ask

What is PEM RSA private key?

PEM encoded RSA private key is a format that stores an RSA private key, for use with cryptographic systems such as SSL. A public key can be derived from the private key, and the public key may be associated with one or more certificate files.

Is a PEM file a private key?

pem file is a container format that may just include the public certificate or the entire certificate chain (private key, public key, root certificates): Private Key.


1 Answers

You say that the last line is throwing exception, i.e.

PrivateKey privKey = kf.generatePrivate(keySpec);

Above line works on keyspecs being set correct, i.e.

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

So actual problem is with encoded bytes array. Have you done System.out after byte [] encoded = Base64.decode(privKeyPEM); and see what the output is.

I understand that if the message is in MIME format, then after certain characters it appends a combination of carriage return and newline so the strings are not too long for e-mail system or wherever you are using it.

The final String test has some '\n' in the original text which you use. You did get rid of other text in below line,

String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

But, look at the string,

"MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" +
// and so on
         "-----END RSA PRIVATE KEY-----";

it may have some more '\n' left which may result in some unwanted characters when you generate keyspec. Try more System.out and see what the encoded byte array is like and also before that check String privKeyPEM and see if any extra character is not left in it.

Hope this hepls.

like image 63
H-Patel Avatar answered Sep 29 '22 17:09

H-Patel