0

I am generating RSA PrivateKey using openSSL in command prompt.

$ openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8

Now this private key needs to decrypt using passphrase to get PrivateKey object which can be used for Authentication. Sample bouncycastle code which is working :

public static PrivateKey getKey()
            throws Exception {
         String filename = "C:\\Snowflake\\rsa_key.p8";
         Security.addProvider(new BouncyCastleProvider());
        PrivateKeyInfo privateKeyInfo = null;
        Security.addProvider(new BouncyCastleProvider());
        // Read an object from the private key file.
         PEMParser pemParser = new PEMParser(new FileReader(Paths.get(filename).toFile()));
            Object pemObject = pemParser.readObject();
        if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
            // Handle the case where the private key is encrypted.
            PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
            String passphrase = getPrivateKeyPassphrase();
            InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
            privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov);
        } else if (pemObject instanceof PrivateKeyInfo) {
            // Handle the case where the private key is unencrypted.
            privateKeyInfo = (PrivateKeyInfo) pemObject;
        }
        pemParser.close();
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
        return converter.getPrivateKey(privateKeyInfo);
    }

But we cannot use bouncycastle bckpix.jar as its having conflict with bcfips.jar as NoSuchField error. Is there any alternate to bouncycastle for do this task ?

This is a sample private key Encrypted using passphrase = "520759"

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIuo49Vz6fm/MCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBAag5K2dYPcW8RoOrg9CfyuBIIE
0M3n8NyQrgmkg9nHPp+qsW8OCPp/ezLR6j1jvo2Rj5/BCRdmFEFLu4S1v9x9ZTDt
CTcq+P8TOeLWgQ1um2Ty8INc4uG5ms0fpvoJ7gIaysnw9vpI/jlhwC3X6xaInWEZ
cU8oU3daz3aHCtgpjulr3Dno3Uj8JadYyoGdSe/ADECHqU3rfqNyOiLWjGx9Se8F
u3LjlM5u/y8KIu25wRHkGho3Rv/0Ns+KOroiIQ3Tdt1AxKAchPfr+MeOA/zH3qJq
IItAxycZG4PL0W70vjYnywzA0go5KgJnq39yDuIYeL7Uj3ygZyKLQEXugiC/eVnH
9ESlTesbGlw6QYlzfD6xPCLG/weT860tuWUCbx9cniZkG0CqHySiSHN0G6H1P+ZS
gTPgiBVBq7hsg0D2BPF3+3DNPhDjuBS/92fR2DPpNayu19tc7HoEnaT9CXSyq4L4
e71N5ybspYmrc+jqFdJEl3rZEKEYzIfmWNADgnmj+/deJl02JIgcyML49v04+ZB2
MrZTQCMC616ErnwmR3iaj2gkgs7IYsSHBAiAZulJWJISQstsKM1TB22ldCFwVT48
MIWG/2XCl4d9+e2beqDy1Jr12VGbdmx/4H20VMsinutGzDKY9JrP6QzLdCQ+/V5j
1ORgar0fewFVlyUBcbWYn8kdY07hZtfV0dW9TV5RLTDK1j9YOSofHW/fHQiTCBwT
jtZUlgFiZCYr9N0Y3pYLcYjwaya9V3rITIp5SCnVXzLMz9TVur8DlgLYwIxW0nhl
QsU/30K9QqM8bq5Iw+I4GD0FqlbO85XelePL4n1eXGERAqbkEZjoNzyoz4hizoX1
kddvcrYi9BNowU5qvJPcbgZ68aupLkljP8le88qv7aAY6Aou6gT64WvbyQA7dpcw
K19cLGbhvNnRGC1Tgj5SB+CzXZZg5iUuFGEXLqreiXdUP8DTOE/uxWBCY/57j6+0
JzFXf0CoqYleGKplkKTjZzF/gorf6RjXiW2bZa2a3c/hhGaslyqCSmX57NWFqjun
N89PnPO8Z8JND1h7wDk8cP9M6rlJiW9BCMTJujNqQaojeeurfWKEsSIPdtEbDTEh
XHSPvLvEJ72Hes7hfpMqiaBuLcm5H7vnNCPXxBbC0Cdwk/yw2S4Mu16nC0HFzSLr
ZzgaKkS0NcrTNOIeY6UhKiJbJgJw9gE6dDEoCbvBy2BsiezAbf6nFO852iW1R1q7
XcRXi0FmBr5UnZusSvxZEHwzcitIV6qdbzeVpNSJUssoBIOaXdsfKGnY4AG9nXXO
8LCPkBBIGXD3amLCPTBKt7XrAgsvCAM+0I07/VGUoKq8p3J62it2/WOdwBAFS0me
tEaIJQVnD2OocFWSxj1UHuBqDaAoCa1dXk2FjlB6jP3p4fhMOooPj/Z+IOYa4Tfr
fgCcLDvVo4sDCAwyExDA7V/zJGa4fRIzyO+iv4q9+aobojhLnFWhxII7e2SdYnGy
5TKLC1hFhBVbv37TOQL0X3W5dnJJXRfhcv2Rce8OqfD1JKDXDETsIrgbTrq2IrPX
ISgdvb6xcC2tD8/7Fo7CC+tMHm5uun9z0rnZIl7ZAuVXA0cfd9cRCp6eksnbc6KR
nhZnW2zER1ABUa9Oq0xqWooAzKd4Ez8Ck/ZKpcC7Nz4o
-----END ENCRYPTED PRIVATE KEY-----
Chanky Mallick
  • 569
  • 8
  • 27

1 Answers1

0

Yes, you can do use an encrypted RSA private key without BouncyCastle, but it's a little bit "tricky".

This is the typical structure of an encrypted RSA key created with nowadays OpenSSL (version >= 1.1.1):

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
    OBJECT IDENTIFIER 1.2.840.113549.1.5.13 pkcs5PBES2 (PKCS #5 v2.0)
    SEQUENCE (2 elem)
      SEQUENCE (2 elem)
        OBJECT IDENTIFIER 1.2.840.113549.1.5.12 pkcs5PBKDF2 (PKCS #5 v2.0)
        SEQUENCE (3 elem)
          OCTET STRING (8 byte) 528FDA1DBEFFE635
          INTEGER 2048
          SEQUENCE (2 elem)
            OBJECT IDENTIFIER 1.2.840.113549.2.9 hmacWithSHA256 (RSADSI digestAlgorithm)
            NULL
      SEQUENCE (2 elem)
        OBJECT IDENTIFIER 2.16.840.1.101.3.4.1.42 aes256-CBC (NIST Algorithm)
        OCTET STRING (16 byte) 9BA62A9EA65CB20CDF39BAEE7262AA45
  OCTET STRING (1232 byte) 8AAFCB6BF8D877804A3E81DB996526334E5AF4F97638C388083B045B2E3A132AD749…

The "real" key is the data in the very last "OCTET STRING" (1232 byte), but it is the encrypted data. The encryption itself is defined by the data above: it is the new encryption scheme pkcs5PBES2 (PKCS #5 v2.0) that uses PBKDF2 for the key derivation with an algorithm hmacWithSHA256. The salt for the key derivation is in the 8 byte long OCTET STRING "528FDA1DBEFFE635".

Edit: for PBKDF2 you need the number of iterations - you find this value in "INTEGER 2048" (2048).

Now we have the key, let's start the encryption using the AES algorithm in mode CBC (aes256-CBC). The randomly generated initialization vector for this task is in the "OCTET STRING" (16 byte): "9BA62A9EA65CB20CDF39BAEE7262AA45".

To get these values programmatically, you have two choices:

  • use an ASN1 parser (smart way) -or-
  • search for the identifier and get the data fields around (rough way).

In the end, it is a simple decryption of the data, and you get a PKCS#8 encoded byte array as input for a "PKCS8EncodedKeySpec" that will "generate" your RSA private key.

For learning purposes I have gone the rough way, and it worked... but as there are some more encryption schemes, key derivations and key encryption algorithms my solution was only good for exact the encryption parameter shown above.

Michael Fehr
  • 5,827
  • 2
  • 19
  • 40
  • Tried many solutions nothing works , I Updated the question with the private key I need to decrypt. This is thread is the closest i reached , https://stackoverflow.com/questions/63832456/parsing-encrypted-pkcs8-encoded-pem-file-programatically Followed the accepted answer by you. But no luck , getting error cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); If you have any Java Code which can decrypt the Key Shared above , pls share , Thanks – Chanky Mallick Sep 14 '21 at 19:51