Load a RSA private key in Java (algid parse error, not a sequence)

Addev picture Addev · Mar 11, 2013 · Viewed 51.2k times · Source

I'm trying to load a private RSA key generated with ssl into java, my code is:

Generate the key:

openssl genrsa -out mykey.pem 1024

Result:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCUibP4fY2PA/sGMKMbU6usuIGcOAqgQjD6c2ylVo05Oz7pgjnE
+O0l2MFRUYUGT5KKk/W+0cAXkxaQHE3n8A8X1mHT8eMDmWnzz0PeYjDE8LQmAw8R
Y2FnVKFAB36BIjdb5FsZmCk5QYKU5+nWLMqH/j/IR5AyX5wR2SMoslUg2QIDAQAB
AoGAeJ1s7638IhLIZtldyRXjRKi6ToFPV50IKodJxOSIXt3WE0V05ZaA84eUSxUY
IOzCgRbuqVmnUz1USAdD18AecC8qc7tXTRALLy7q8fxklPwmGPUOvTFmI7gRMUnv
cWrq1gySk3SKpj0YmWnuY9Xmd2+xoWLzUeFD1CROY5OTjIECQQDDlp1+Al7+duR0
XyMlkWLIk0nIbkQ5zlTAEipzmaeTSOJi6YG3EMMz3AGuZb7tw6HFxWqeg1hyKJ+T
cTM3WTdJAkEAwmrCDKE29n3wFOBKsZZFQbDgVOUXCBs2ubEI+ALe1DJU5BlfnrhJ
OINRCNgnwSFNbwxDTkDpR6J6Av2ElAvNEQJAV0dVvk5Wj50Ecz2lFHWdLD41taAn
B9igDxnMIcvWcK4cf+ENhmCPiwvJIEa8/aLIBNYErvmTtVWVaBkirrc8KQJABr+z
+sJB6S6X/fGHRkDkKJKeRvQo54QiUzHdENbwq0cQAVcMJbNZ/1c3oen2/1JLoNY5
I+dG8dCnEaGBT65VMQJBAIDqH1Kqs5tb51cpt6h9ot31SUVud5pSML/babwp3pRs
1s6poreym4PkAyRug0Dgcj1zVLt25TlOHvrL9r3Swq8=
-----END RSA PRIVATE KEY-----

Load:

String privKeyPEM=readFile("mykey.pem");
privKeyPEM= privKeyPEM.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("\n", "");
// Remove the first and last lines
privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
System.out.println(privKeyPEM);

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

// PKCS8 decode the encoded RSA private key
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);

// Display the results
System.out.println(privKey);

and it throws an IOException : algid parse error, not a sequence. Where is the error?

Exception in thread "main" 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 base54.encrypt.RSAToy.main(RSAToy.java:36)
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)

Answer

Michael Herrmann picture Michael Herrmann · Mar 4, 2014

Further to Julien Kronegg's answer, if you are getting this error because your file has a PKCS#1 format, you can use the following steps to convert it to a PKCS#8 file.

First, save your PKCS#1 key file to a file called priv1.pem:

-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----

Then, execute the following command:

openssl pkcs8 -topk8 -inform PEM -outform PEM -in priv1.pem -out priv8.pem -nocrypt

This produces a file called priv8.pem, which is your key file in PKCS#8 format:

-----BEGIN PRIVATE KEY-----
[...]
-----END PRIVATE KEY-----

I use this from Java as follows:

String PRIVATE_RSA_KEY_PKCS8 = 
    "-----BEGIN PRIVATE KEY-----\n" +
    "MDSTofml23d....\n" +
    [...] +
    "-----END PRIVATE KEY-----\n";
String key = PRIVATE_RSA_KEY_PKCS8
    .replace("-----BEGIN PRIVATE KEY-----\n", "")
    .replace("\n-----END PRIVATE KEY-----\n", "");
PKCS8EncodedKeySpec keySpec =
    new PKCS8EncodedKeySpec(DatatypeConverter.parseBase64Binary(key));
try {
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] bytes = parseBase64Binary(encryptedNodeIdentifier);
    byte[] decryptedData = cipher.doFinal(bytes);
    return new String(decryptedData);
} catch (GeneralSecurityException e) {
    return "";
}