用于解密加密 p8 文件的 BouncyCastle 替代方案

Posted

技术标签:

【中文标题】用于解密加密 p8 文件的 BouncyCastle 替代方案【英文标题】:BouncyCastle Alternative to Decrypt a Encrypted p8 file 【发布时间】:2021-11-01 05:56:53 【问题描述】:

我正在命令提示符中使用 openSSL 生成 RSA PrivateKey。

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

现在这个私钥需要使用密码解密以获得可以用于身份验证的 PrivateKey 对象。正在运行的示例 bouncycastle 代码:

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);
    

但是我们不能使用 bouncycastle bckpix.jar,因为它与 bcfips.jar 冲突,因为 NoSuchField 错误。 是否有任何替代 bouncycastle 来执行此任务?

这是使用 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
XcRXi0FmBr5UnZusSvxZEHwzcitIV6qdbze***SJUssoBIOaXdsfKGnY4AG9nXXO
8LCPkBBIGXD3amLCPTBKt7XrAgsvCAM+0I07/VGUoKq8p3J62it2/WOdwBAFS0me
tEaIJQVnD2OocFWSxj1UHuBqDaAoCa1dXk2FjlB6jP3p4fhMOooPj/Z+IOYa4Tfr
fgCcLDvVo4sDCAwyExDA7V/zJGa4fRIzyO+iv4q9+aobojhLnFWhxII7e2SdYnGy
5TKLC1hFhBVbv37TOQL0X3W5dnJJXRfhcv2Rce8OqfD1JKDXDETsIrgbTrq2IrPX
ISgdvb6xcC2tD8/7Fo7CC+tMHm5uun9z0rnZIl7ZAuVXA0cfd9cRCp6eksnbc6KR
nhZnW2zER1ABUa9Oq0xqWooAzKd4Ez8Ck/ZKpcC7Nz4o
-----END ENCRYPTED PRIVATE KEY-----

【问题讨论】:

【参考方案1】:

是的,您可以在没有 BouncyCastle 的情况下使用加密的 RSA 私钥,但这有点“棘手”。

这是使用当今 OpenSSL(版本 >= 1.1.1)创建的加密 RSA 密钥的典型结构:

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…

“真正的”密钥是最后一个“OCTET STRING”(1232 字节)中的数据,但它是加密数据。加密本身由上面的数据定义:它是新的加密方案 pkcs5PBES2 (PKCS #5 v2.0),它使用 PBKDF2 通过算法 PBKDF2 进行密钥派生强>hmacWithSHA256。密钥派生的 salt 在 8 字节长的 OCTET STRING "528FDA1DBEFFE635" 中。

编辑:对于 PBKDF2,您需要 迭代次数 - 您可以在 "INTEGER 2048" (2048) 中找到该值。

现在我们有了密钥,让我们在 CBC 模式 (aes256-CBC) 下使用 AES 算法开始加密。此任务随机生成的初始化向量位于“OCTET STRING”(16 字节)中:“9BA62A9EA65CB20CDF39BAEE7262AA45”。

要以编程方式获取这些值,您有两种选择:

使用 ASN1 解析器(智能方式)-或- 搜索标识符并获取周围的数据字段(粗略)。

最后,这是对数据的简单解密,您会得到一个 PKCS#8 编码字节数组作为“PKCS8EncodedKeySpec”的输入,它将“生成”您的 RSA 私钥。

出于学习目的,我采用了粗略的方法,但它确实有效……但由于有更多的加密方案、密钥派生和密钥加密算法,我的解决方案仅适用于上面显示的加密参数。

【讨论】:

尝试了很多解决方案都没有效果,我用我需要解密的私钥更新了这个问题。这是我到达的最接近的线程,***.com/questions/63832456/… 遵循您接受的答案。但没有运气,得到错误 cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);如果您有任何可以解密上面共享的密钥的 Java 代码,请分享,谢谢

以上是关于用于解密加密 p8 文件的 BouncyCastle 替代方案的主要内容,如果未能解决你的问题,请参考以下文章

从 cert 文件中获取 Secret Key 以用于 AES 算法进行加密和解密

文件怎样可以解密呀

文件夹加密了然后就解密不了

如何通过公钥加密文件

powershell Encrypt-Config.ps1:用于加密或解密.NET app.config文件的PowerShell工具

python怎么对文件进行加密解密