3

I need to convert an RSA private key located in memory in PEM format into a PrivateKey on Android.

The problem seems to have been solved for public keys but I'm struggling to get it to work for a private key. I'm trying the following code:

String pemkey = "MIICWwIBAAKBgQDIuL0SzG1+wgyaoyDyHvYIaG10ePXBHqaKTnYyZfY5RzaEFLE/vBdFN2Di7AMH3/5iN/YFQqLsVjKqzX3E3LM2dJOZ9qSWeYArSyQPbhy0eM/3amwchvtLvhVLm2UqVFLjiPGlyYX3D75ETD5tmgulAc5ZDRtGqYVoLKPmZ0USPwIDAQABAoGAErfDjf65UUJISZ1fw6Rmfic62csz47P3hNtHQ3Dlsra020FQvChOpTpCUzb+G1xkjQU58Iijx9VL+Uiba2HHZmiJX2LgS3KKqKFZKmbKZnZQTiw+2o+4AXhtcAYfSAJE9TgRPEhwhZmzV2cvfUk5AjnOghSn2gGjdD1g4xtH22ECQQD/ZbfEd2HEGqHf6j/AVMW+N/Q1xtYIB8r0CWxF6cNw5iq/8Ce9ujpnAFi0vgtojyKDlgwBp4XMU2C4is49EkFhAkEAyTH96mS8dExAAmi3Mm2seUIEOtKwuLD6BEECecPyZSIOd24tfNbmA7Ri6MpGjyLZoNoJQ0AJGcnWU1tnc8bXnwJAS+jYyP1OwrHDwUDnt+u6ZoJNBJrXzMU8LnKKivEjFPBkbm4b8cljSHAS7Y266FX6xS+Y2/kFzKhPjCo9iGtfoQJAOv39hYyj9TWmTw6FKLQfri49L0I3ru+1Xynwn+NkX2Ls+vfDPqeEKfHqTneA2NdPGGrV7HIKORWFUkuqubfD4QJAK60RuhDSeH+ZljcYLhbHLoTnja/uTcvDAd0M4ll2HUNId4jPbYl1qw7OQwfg8apKmGwp7HGW50o/EItvvJrR7w==";
byte[] encoded = Base64.decode(pemkey, Base64.DEFAULT);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey sessionkey = kf.generatePrivate(keySpec);

(The key is not the same as for my Bitcoin wallet so don't bother ^^)

The last line gives the error

java.security.spec.InvalidKeySpecException:
        Must use RSAPublicKeySpec or PKCS8EncodedKeySpec;
        was java.security.spec.X509EncodedKeySpec

I tested the pemkey string to be ok in other languages (e.g. Python RSA.importkey) and it works fine.

Edit:

On a suggestion by a comment (and the answer to the question linked as doublicate), I also tried with X509EncodedKeySpec replaced by PKCS8EncodedKeySpec. Then the new error I get is

java.security.spec.InvalidKeySpecException:
        java.lang.RuntimeException:
        error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
matec
  • 1,316
  • 1
  • 10
  • 22
  • Can you try using `PKCS8EncodedKeySpec` for the private key and `RSAPublicKeySpec` for the public one. Tell me if it works, but for sure you must use the new private key – Greggz Dec 31 '17 at 17:15
  • I get `java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag` after replacing `X509EncodedKeySpec` by `PKCS8EncodedKeySpec`. – matec Dec 31 '17 at 17:23
  • Possible duplicate of [Android Save RSA Private and Public Key](https://stackoverflow.com/questions/28306782/android-save-rsa-private-and-public-key) – Greggz Dec 31 '17 at 17:28
  • plz look at the link I posted as duplicate – Greggz Dec 31 '17 at 17:29
  • 1
    It's not a PKCS8EncodedKeySpec, it's a raw RSA private key. The answer is always "don't do that". Convert the key to a PKCS8Encoded keyspec. [Easy](https://stackoverflow.com/a/7473874/238704) answer. [Harder](https://stackoverflow.com/a/3251645/238704) answer. – President James K. Polk Dec 31 '17 at 20:57

1 Answers1

3

Thanks to comments by Greggz and James I was able to get it to work. There were two problems:

  • X509EncodedKeySpec had to be replaced by PKCS8EncodedKeySpec
  • The provided pemkey was PKCS#1 (to be recognized by 'BEGIN RSA PRIVATE KEY') but needs to be PKCS#8 (to be recognized by 'BEGIN PRIVATE KEY').
matec
  • 1,316
  • 1
  • 10
  • 22