用于解密加密 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工具