I can generate a PKCS#8 encrypted file with empty password using OpenSSL:
~ $ openssl pkcs8 -topk8 -in ca_private.pem
Enter pass phrase for ca_private.pem:
Enter Encryption Password: <ENTER>
Verifying - Enter Encryption Password: <ENTER>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIsWq90VBNFMwCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCFtKOCdDUeRohccAqQZaDIBIIB
YG+ohLBKQ766BTCXXZ7wyAP1l0grcQPgnzI2XmEj33rBIMogS6l3oAN3Faos2I6n
PcUY+aNLQtDSbvPzF4ozd0oWYBTa60iYGboQQ2RolhRRTzNW6K2tWBWUB35v2rLV
VYu7xJMX+dr/PxzhEgaQ4Nerb7v7/EAn4fLv3zcW9f/tPbljKUAiKc/YYP+GjRjA
GyJThdVpyeK6Jflobc3V8gqL8Gk0MgeHmXuUR1+SthA6ia5havH7D/FMLvXxZtRK
CpWOQ8mJp7g7dbUf+qWTLX+dMPQFPZDEofdkCY2/J4dSkgNnPgp+1oxSVpEAAR9v
gWsRezU2KfFUEMIljYOT+s4ZhkeAGtA8qa8qnr0yv9uz1OkzFtrleNf0WV8wRqI7
azo/7ff9TbecseYlTRgR40nd2l3Z9RLMVhsS09vPffYDw3jt+Zqf3m7iEri6eSug
5bMcZTszaQsVT0HOfCcpQ1Q=
-----END ENCRYPTED PRIVATE KEY-----
When reading this with a PEMParser, it returns an instance of PKCS8EncryptedPrivateKeyInfo (as expected).
Trying to decrypt that with JceOpenSSLPKCS8DecryptorProviderBuilder, however, fails with
org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: password empty
There is a hard coded check for empty password when creating the decryption key. Is there a way around this? OpenSSL surely deals just fine reading the PKCS#8 back...
Sample code:
import com.excelfore.api.lib.util.ApiCrypto;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import java.io.FileReader;
class Scratch {
public static void main(String[] args) throws Exception {
try (FileReader fr = new FileReader(args[0])) {
Object whatIsIt = new PEMParser(fr).readObject();
if (whatIsIt instanceof PKCS8EncryptedPrivateKeyInfo) {
PKCS8EncryptedPrivateKeyInfo pInfo = (PKCS8EncryptedPrivateKeyInfo) whatIsIt;
InputDecryptorProvider provider =
new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider(ApiCrypto.bouncyCastleProvider).build(args[1].toCharArray());
pInfo.decryptPrivateKeyInfo(provider);
System.out.println("ok");
} else {
System.out.println("I don't want "+whatIsIt.getClass().getName());
}
}
}
}
Not sure if there is what you expect or not (do not test yet with empty passphrase)
public static KeyPair parseKeyPair(Path pemFile, String passPhrase) {
try(PEMParser pemParser = new PEMParser(Files.newBufferedReader(pemFile))) {
Object object = pemParser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProviderHolder.BC_PROVIDER);
if(object instanceof PEMEncryptedKeyPair) {
if(passPhrase == null)
throw new IllegalArgumentException("Pass phrase required for parsing RSA private key");
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passPhrase.toCharArray());
return converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
}
if(object instanceof PEMKeyPair) {
return converter.getKeyPair((PEMKeyPair) object);
}
} catch(Exception e) {
throw new PicApplicationException("Couldn't parse pem to keypair", e);
}
throw new PicApplicationException("Couldn't parse pem to keypair");
}
You may pass empty passphrase to this line:
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build("".toCharArray());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With