22

With a PEM certificate like

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,B9846B5D1803E.....

using BC 1.46, I extract the keypair with the following code :

int myFunc(String pemString, char [] password) {

    ByteArrayInputStream tube = new ByteArrayInputStream(pemString.getBytes());

    Reader fRd = new BufferedReader(new InputStreamReader(tube));

    PEMReader pr = new PEMReader(fRd, new Password (password), "BC");

     try {
            Object o = pr.readObject();
            if (o instanceof KeyPair)
    .....

Now I just installed BC 1.48, and they tell me that PEMReader is deprecated and must be replaced by PEMParser.

My problem is, AFAIK, there is no place for a password in PEMParser.

Could someone give me an example how to migrate my code to a PEMParser version ?

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
stackanovist
  • 321
  • 1
  • 2
  • 3

2 Answers2

39

I just needed to solve the same problem and found no answer. So I spent some time studying BC API and found a solution which works for me. I needed to read the private key from file so there is privateKeyFileName parameter instead pemString parameter in the myFunc method.

Using BC 1.48 and PEMParser:

int myFunc(String privateKeyFileName, char [] password) {
     File privateKeyFile = new File(privateKeyFileName); // private key file in PEM format
     PEMParser pemParser = new PEMParser(new FileReader(privateKeyFile));
     Object object = pemParser.readObject();
     PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password);
     JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
     KeyPair kp;
     if (object instanceof PEMEncryptedKeyPair) {
        System.out.println("Encrypted key - we will use provided password");
        kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
    } else {
        System.out.println("Unencrypted key - no password needed");
        kp = converter.getKeyPair((PEMKeyPair) object);
    }
}
xwatch
  • 391
  • 2
  • 2
  • 5
    If the private key is in PKCS#8 format, the object will be an instanceof PrivateKeyInfo. You'll have to use `converter.getPrivateKey((PrivateKeyInfo) object);` – gtrig Nov 20 '13 at 03:18
  • 1
    Brilliant, this helped me adapt my usage of the deprecated BC 1.46 org.bouncycastle.openssl.PEMReader class to the newer PEMParser technique. Thank you so much! – Goffredo Nov 19 '14 at 01:50
  • 2
    @xwatch Hello, could you provide imports please? Can't find the class PEMParser -I'm kind of new- using MAVEN and I have this dependency org.bouncycastle bcprov-jdk15on 1.56 Can't get it to work. – Juan Carlos Apr 24 '17 at 23:44
  • @JuanCarlos you need to use `org.bouncycastle`, `bcpkix-jdk15on` artifact – Ivan Stanislavciuc Feb 11 '19 at 10:35
2

For Version 1.55 of bcpkix-jdk15on the decryption code changes to this:

kp = ((PEMEncryptedKeyPair) object).decryptKeyPair(decryptorProvider);

I didn't check if this is a mistake in the above answer or just an API difference between the versions.

jonas
  • 185
  • 8