bcgit / bc-java

Bouncy Castle Java Distribution (Mirror)
https://www.bouncycastle.org/java.html
MIT License
2.27k stars 1.12k forks source link

Failed to parse the private key file of Ed25519! #1238

Open chen0411 opened 1 year ago

chen0411 commented 1 year ago

try to parser the private key file of ed25519, and fail , how to fix it ?

  1. Private key file content: -----BEGIN PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,b619a06a16b7b7a6436579f06a14f45e

QmysBFzoMkgvVTM39kvHjkKhcBjK6PVMZ6a/taF44ZXeOl3t5DUp4EWxyfs8htng tjsKIb0yKJigIZGrCeHROQ== -----END PRIVATE KEY-----

  1. exception info: org.bouncycastle.openssl.PEMException: problem parsing PRIVATE KEY: java.lang.IllegalArgumentException: failed to construct sequence from byte[]: corrupted stream - out of bounds length found: 108 >= 64 at org.bouncycastle.openssl.PEMParser$PrivateKeyParser.parseObject(Unknown Source) at org.bouncycastle.openssl.PEMParser.readObject(Unknown Source) ....

  2. core code: ` PrivateKeyInfo pki; try (PEMParser pemParser = new PEMParser(new StringReader(encryptPrivateKey))) { Object o = pemParser.readObject(); if (o instanceof PKCS8EncryptedPrivateKeyInfo) { PKCS8EncryptedPrivateKeyInfo epki = (PKCS8EncryptedPrivateKeyInfo) o; JcePKCSPBEInputDecryptorProviderBuilder builder = new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC"); InputDecryptorProvider idp = builder.build(password.toCharArray()); pki = epki.decryptPrivateKeyInfo(idp);

        } else if (o instanceof PEMEncryptedKeyPair) {
            PEMEncryptedKeyPair epki = (PEMEncryptedKeyPair) o;
            PEMKeyPair pkp = epki.decryptKeyPair(new BcPEMDecryptorProvider(password.toCharArray()));
            pki = pkp.getPrivateKeyInfo();
        } else {
            log.error("Invalid encrypted private key class:{}", o.getClass().getName());
            return null;
        }
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
        return converter.getPrivateKey(pki);
    } catch (Exception e) {
        log.error("loadPrivateKey exception:{}", ExceptionUtil.getBriefExceptionStackTrace(e));
    }
    return null;`
dghgit commented 1 year ago

Usually this would mean the password is wrong, it's possibly an issue with the PBE algorithm, but given how long it has been since we have had a report like this, I'd check the password.

chen0411 commented 1 year ago

Usually this would mean the password is wrong, it's possibly an issue with the PBE algorithm, but given how long it has been since we have had a report like this, I'd check the password.

I don't think it was the wrong password that caused the problem;The exception occurs when this line of code is executed:Object o = pemParser.readObject(); When I parse private key files generated by other algorithms (RSA/EC) in the same way, it's OK; I think the class (PEMParser ) does not support parsing the ed25519 private key encrypted in the preceding format;

dghgit commented 1 year ago

It should decrypt to a private key object, as in a PKCS#8 PrivateKeyInfo. If there was an issue with the fact it was ed25519 then the problem would show up trying to interpret the contents of the PrivateKeyInfo

peterdettman commented 1 year ago

@dghgit It's not an ENCRYPTED PRIVATE KEY, it's a PRIVATE KEY using PEM encryption. While KeyPairParser supports the PEM encryption (returning a PEMEncryptedKeyPair), PrivateKeyParser doesn't have a pathway to e.g. a "PEMEncryptedPrivateKey".

dghgit commented 1 year ago

Oh yeah... think it must be a slow day today. Let me think about this further. @chen0411 would you provide a sample with a password.

chen0411 commented 1 year ago

Oh yeah... think it must be a slow day today. Let me think about this further. @chen0411 would you provide a sample with a password.

Yes, password is: Vjvyhfngz0MCUs$kwOF0 private key:

-----BEGIN PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,b619a06a16b7b7a6436579f06a14f45e

QmysBFzoMkgvVTM39kvHjkKhcBjK6PVMZ6a/taF44ZXeOl3t5DUp4EWxyfs8htng tjsKIb0yKJigIZGrCeHROQ== -----END PRIVATE KEY-----

and can use openssl command to change the private key to ENCRYPTED PRIVATE KEY. for example: image

timw commented 1 year ago

I think this is an example of what I was describing in #1350 - this is a PKCS8 PrivateKeyInfo encrypted with the 'traditional' PEM method. It looks like openssl can read such keys (although I've yet to find a way to get it to generate them), but BC just sees it as an unencrypted PKCS8 key, and the subsequent error messages are it trying to parse the random data as a PrivateKeyInfo.

@chen0411 - was the original encrypted key generated by BC or something else?