使用 Bouncy Castle 解密 PEM 私钥 (RSA)

Decrypt PEM private (RSA) key with Bouncy Castle

目标:从加密的 PEM 文件中提取 RSA 私钥。私钥将用于以编程方式签署证书。

环境:Java 8 和充气城堡 1.52


使用 Bouncy Castle PEMParser(导致 PKCSException)

    //Register BC as a crypto provider
    Security.addProvider(new BouncyCastleProvider());

    //Get file handle
    String caPrivateKeyFname = "cakey.pem";
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(caPrivateKeyFname);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    //Load and parse PEM object
    PEMParser pemRd = new PEMParser(new InputStreamReader(fis));
    Object objectInPemFile = pemRd.readObject();

    //I do not know why BC loads the file as a PKCS8 object. OpenSSL does not recognize it as such.
    PKCS8EncryptedPrivateKeyInfo keyInfo = (PKCS8EncryptedPrivateKeyInfo) objectInPemFile;

    //Decrypt the private key
    String pwd = "secret";
    InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(pwd.toCharArray());

    //Next statement raises an exception.
    PrivateKeyInfo privateKeyInfo = keyInfo.decryptPrivateKeyInfo(pkcs8Prov);

Exception in thread "main" org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: 1.2.840.113549.1.5.13 not available: Illegal key size
    at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source)
    at org.codice.ddf.certificate.SignedCertificate.main(SignedCertificate.java:67)
Caused by: org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.13 not available: Illegal key size
    at org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder.get(Unknown Source)
    ... 2 more
Caused by: java.security.InvalidKeyException: Illegal key size
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1060)
    at javax.crypto.Cipher.implInit(Cipher.java:809)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
    at javax.crypto.Cipher.init(Cipher.java:1539)
    at javax.crypto.Cipher.init(Cipher.java:1470)
    ... 3 more  

* 更新 *

openssl asn1parse -in cakey.pem

PBES2

PBKDF2

des-ede3-cbc

如果我没理解错的话,DES密钥长度是64位,所以3DES是192位密钥。 但是,Java 策略将 DES 密钥的长度限制为 56 位,因此 3DES 的最大密钥长度为 168 位。

关闭管辖政策文件对我来说不是一个选择。我认为有一种方法可以用 Bouncy Castle 解密 PKCS8 加密的私钥,但该解决方案比将提供者设置为 BC 更复杂。

谁能给我举个例子或提供一些参考代码?

(感谢 dave_thompson_085 的帮助)。

是的,以“-----BEGIN ENCRYPTED PRIVATE KEY-----”行开头的文件是 PEM 格式的 PKCS#8 加密私钥。我不知道为什么你的评论说 "OpenSSL does not recognize it"; openssl rsa 成功读取它的事实证明 OpenSSL 确实识别它。

BC PKCSException 只是一个包装器;你的实际问题java.security.InvalidKeyException: Illegal key size。如果您尝试在 JRE 中使用优于 128 位的对称加密或(如此处)解密,而该 JRE 具有默认的 shipped-by-Sun-now-Oracle 加密策略,该策略仅限于 128 位对称。我敢打赌 openssl asn1parse <cakey.pem 显示使用 PBES2 使用 PBKD2(带有一些参数)和 aes-192-cbcaes-256-cbc.[=19 加密的文件=]

从 [=18= 的 "Additional Resources" 部分下载 JDK/JRE 8 的“... (JCE) Unlimited Strength Jurisdiction Policy Files” ] 然后解压,把两个*policy.jar文件放到你用的JRE的JREHOME/lib/security目录下。 (假设你没有受到美国的制裁,因为你在朝鲜、伊朗或叙利亚政府等。)