2

I am having below RSA private key in string format.

String privatekey = -----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqAKCCMKqboM8ywSuNvmf2zuT0e2elxntdEe5msv22jzT89Xa
1Q/V4CeQdZruIw8eTAMa67Dej+3cPdSrjdDnfxcb9L14U9oFPgOyvxVwb+/S8jqm
F9o7Gvm85X972C8izh+K4ndpPtztxkZ0g7cu7RqrCCBzw5SUfi3pgIpprdiKlVDP
4lF7CTwzRH+oi+BxwOABEiuKOJtjOXX1WJhV6ukEy8K6Fq/QOyt/7vgxkm8I8HMo
SMq2UZNswn5/9SqMWuaTBaQbjZ2f77zaq5X/jOiCThTxFNPjPnzhKhG8ekaqIUpB
y9VuICFgdtVQimnlDykrdJWyeOFWPjYl5vehkwIDAQABAoIBAQCN2Ig2ozvHUA/s
i8gWbAyVyKgVrhueEOrUqJXAZoHEYWTFUgGOru7wcBbb4/E4MlRu8pQw90QAml6+
6SXp9rzsJPOaXrkPelvArtij0ZL7PqyHjBKcwsfyD3V3AXnq3GjzQ9g7OXvm8hnh
s6w9ZFQ/JKvPka6LKo9wNI0W1EVC2tggN0Jt6YJFU7trb5TtiQm/B4NKpflZ7PsC
1WOttz0q+VSzF/p04+33OLXugF1crgMr9KCg0uSPi5zCcM+3RVSWDrcZoh+yV4pK
+g5XKKw/BQD9vrUzsLMDjupp4Is0sSEXwMQeRbUZRnUOWVO7E7jrawzhGXV6v4ZT
3PoxB7CxAoGBANkK9ITnfIr1AlF8S1Ok12AlHLYvCPG4TVBw4WNVUX1y3wBXpOmx
t5S2wGpTmyf3LBpw/0m+5EzoghjSb2QnIRFveAxuhxPCPNqxvyzm2D7ycaGJX41y
RfsxvWVQpzvCVH4yV+tkH107ivR2uFDtbDjqlydPyIxmA1Frlm87CODpAoGBAMYq
gLO5EEKxs1MlCzZkuqsEAq+kZVX7y3Kw9rzCJtRQKfYu0IlNFudPg3KpqcbQsrfR
1Psl6iTLXtLe+92NXDOcc9rfj9crmAKmZA1llXOwxe4FOrLWbxk+i6V3qJ2qrf+I
Dwc9+Xrc6ydcDtTHAi3JeIReEbDMvFc6JRiyjwEbAoGAeH68gYyCeCLNxq9aonVB
nP79kadLL+dCBQamGp+jPiIn6+i8hYFEiitrZ5xC500yDvvsvuRbmtb6Yw1xCgkv
Mp7P5xb1puKPJlrH6AXAyDGRJD0/7ych8vMKUtUUAvlAL0+DwAs13mzQGChQ65zk
GDUk9Y41qLx52xn/yoDbzQECgYEAksM9qF1iPpLPBcAEqtc1LJz+xEiTyHeAOMP5
KNj92vY37ZzEUzulv9AywQQIujcsdVlRTGPLIk8APlpo3K/p3kt7vlkedbRSk3vZ
09YtNo5wOJTk4ThQ9bhNwlF5rrOOxBZnUuzCTQ06l17lmQ5+fZydxiLJJVCsGEn2
2XC82osCgYB9maZnLrSZ3Xq4X256/H+Et8TcgqOZGbLuGkNzheheP/E5LcUhQqbP
oJRB24XoX+yw+Do5q2pHHgbrrHwcdg3Xfw9sb5P2JNbtG57mO7QEilIHfUQzQl/U
XSKgJJZ/9bTPlbZmp9ChM9izUv8DI5vjhDputhlEHP4BpHBN03a85Q==
-----END RSA PRIVATE KEY-----

I am trying to convert this to PrivateKey type using below code snippet-

  public PrivateKey generatePrivateKey(String privateKey) throws Exception{

        privateKey = privateKey.replace("-----BEGIN RSA PRIVATE KEY-----", "");
        privateKey = privateKey.replace("-----END RSA PRIVATE KEY-----", "");
        privateKey = privateKey.replaceAll("\\s+", "");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey.getBytes());
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(keySpec);
    }

I am getting below error -

It is giving me an error on generatePrivate method.

Execution exception[[InvalidKeySpecException: java.security.InvalidKeyException: invalid key format]]

Tried using the answer here Java: Convert DKIM private key from RSA to DER for JavaMail

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Base64;

public class pkcs1ToPkcs8 {

    public static void main(String[] args) throws IOException {

        String pkcs1 = //privatekey provided above

            // b64 now contains the base64 "body" of the PEM-PKCS#1 file
            byte[] oldder = Base64.getDecoder().decode(pkcs1.getBytes());

            // concatenate the mostly-fixed prefix plus the PKCS#1 data 
            final byte[] prefix = {0x30,(byte)0x82,0,0, 2,1,0, // SEQUENCE(lenTBD) and version INTEGER 
                    0x30,0x0d, 6,9,0x2a,(byte)0x86,0x48,(byte)0x86,(byte)0xf7,0x0d,1,1,1, 5,0, // AlgID for rsaEncryption,NULL
                    4,(byte)0x82,0,0 }; // OCTETSTRING(lenTBD) 
            byte[] newder = new byte [prefix.length + oldder.length];
            System.arraycopy (prefix,0, newder,0, prefix.length);
            System.arraycopy (oldder,0, newder,prefix.length, oldder.length);
            // and patch the (variable) lengths to be correct
            int len = oldder.length, loc = prefix.length-2; 
            newder[loc] = (byte)(len>>8); newder[loc+1] = (byte)len;
            len = newder.length-4; loc = 2;
            newder[loc] = (byte)(len>>8); newder[loc+1] = (byte)len;

            FileOutputStream fo = new FileOutputStream ("pkcs8_file");
            fo.write (newder); fo.close();
            System.out.println ("converted length " + newder.length);

    }

}
user1896796
  • 731
  • 3
  • 9
  • 25

1 Answers1

2

BEGIN RSA PRIVATE KEY means your key is pkcs#1 format and not pkcs#8. Reading pkcs#1 keys is not natively supported by Java. You need to use bouncycastle library ( see Read RSA private key of format PKCS1 in JAVA )or use any of these solutions Getting RSA private key from PEM BASE64 Encoded private key file


if your key were pkcs#8, it would have the header BEGIN PRIVATE KEY. In that case, for your code to work correctly you would need additionally decode the key content from base64


To convert a pkcs#1 key to pkcs#8 you can use openssl

  openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in pkcs1.key -out pkcs8.key
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • I tried with `PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey.getBytes()));`. It is giving me `[InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence]` error. – user1896796 Apr 14 '19 at 17:19
  • Maybe the second part of my answer is confusing. Your key is not PKCS # 8 so you have to use bouncycastle or an alternative solution like the linked ones. – pedrofb Apr 14 '19 at 17:31
  • I went through the solutions . Couldn't find which one to use. I need to convert this key to pkcs8 ? How can I do this if not using bouncycastle. – user1896796 Apr 14 '19 at 17:45
  • The accepted answer of the second link should work to load your current key. If you prefer to convert the key to pkcs#8 you can use openssl. See updated answer – pedrofb Apr 14 '19 at 18:46
  • 1
    The accepted answer #20748064 uses spongycastle which _is_ bouncycastle, so this doesn't satisfy the condition of not using bouncycastle. #33594033 or #55339208 works, and I had a similar approach at https://stackoverflow.com/questions/23709898 . Concur `openssl pkcs8 -topk8 -nocrypt` (or in 1.0.0 up just `openssl pkey`) is another option. – dave_thompson_085 Apr 14 '19 at 19:24
  • @dave_thompson_085 Which one according to you is better to use. #33594033 looks less code. – user1896796 Apr 15 '19 at 09:58
  • @pedrofb Just wanted to check . At the start I have generated key pair which is pkcs1 key. If I am encrypting some data using the converted pkcs8 private key. Will I be able to verify the signature using the public key generated at the start.??? – user1896796 Apr 15 '19 at 11:59
  • @user1896796, pkcs# 8 and pkcs#1 are formats for encoding the private key. The parameters of the private key are the same regardless of the format. Therefore the verification of the digital signature will not have any relation with the format in which the key is stored. You can use any of the two answers indicated by dave_thomsom, those that include bouncycastle, or openssl because the private key will remain the same – pedrofb Apr 15 '19 at 12:41
  • @user1896796: according to me bouncycastle is better but you've ruled that out. Of the rest personally I like the style of the one I wrote because I write in the style I like, but they all do effectively the same thing so if you prefer a different style from me that's fine. – dave_thompson_085 Apr 16 '19 at 01:30