BouncyCastle冲突场景下解密加密p8格式RSA私钥的替代方案咨询
问题描述
我通过命令行使用openSSL生成RSA私钥,执行命令如下:
$ openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8
生成的私钥为加密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相关组件,请问有没有替代BouncyCastle实现该需求的方案?
以下是密码为"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 XcRXi0FmBr5UnZusSvxZEHwzcitIV6qdbzeVpNSJUssoBIOaXdsfKGnY4AG9nXXO 8LCPkBBIGXD3amLCPTBKt7XrAgsvCAM+0I07/VGUoKq8p3J62it2/WOdwBAFS0me tEaIJQVnD2OocFWSxj1UHuBqDaAoCa1dXk2FjlB6jP3p4fhMOooPj/Z+IOYa4Tfr fgCcLDvVo4sDCAwyExDA7V/zJGa4fRIzyO+iv4q9+aobojhLnFWhxII7e2SdYnGy 5TKLC1hFhBVbv37TOQL0X3W5dnJJXRfhcv2Rce8OqfD1JKDXDETsIrgbTrq2IrPX ISgdvb6xcC2tD8/7Fo7CC+tMHm5uun9z0rnZIl7ZAuVXA0cfd9cRCp6eksnbc6KR nhZnW2zER1ABUa9Oq0xqWooAzKd4Ez8Ck/ZKpcC7Nz4o -----END ENCRYPTED PRIVATE KEY-----
解决方案
可直接使用JDK原生API实现需求,无任何第三方依赖,完全避免BouncyCastle相关的jar包冲突问题,完整实现代码如下:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import javax.crypto.EncryptedPrivateKeyInfo; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; public class RsaKeyLoader { public static PrivateKey getKey(String keyFilePath, char[] passphrase) throws Exception { // 1. 读取PEM文件内容,处理格式 String pemContent = Files.readString(Paths.get(keyFilePath)); // 去除头尾标记和所有换行、空格 String encodedKey = pemContent .replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "") .replace("-----END ENCRYPTED PRIVATE KEY-----", "") .replaceAll("\\s+", ""); // Base64解码得到DER二进制内容 byte[] encryptedKeyBytes = Base64.getDecoder().decode(encodedKey); // 2. 解析加密的PKCS8私钥 EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(encryptedKeyBytes); // 生成解密用的密钥 PBEKeySpec pbeKeySpec = new PBEKeySpec(passphrase); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName()); // 3. 解密得到明文私钥的编码 PKCS8EncodedKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(secretKeyFactory.generateSecret(pbeKeySpec)); // 4. 生成RSA私钥对象 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } // 测试用例 public static void main(String[] args) throws Exception { PrivateKey privateKey = getKey("C:\\Snowflake\\rsa_key.p8", "520759".toCharArray()); System.out.println("私钥加载成功,算法:" + privateKey.getAlgorithm()); } }
说明
- 该实现兼容JDK 8及以上所有版本,不需要引入任何额外jar包
- 同时支持你生成的加密PKCS8格式私钥,也可扩展支持未加密的PKCS8私钥(直接解析PKCS8EncodedKeySpec即可)
- 你提供的示例私钥可通过上述代码正常解密使用
内容的提问来源于stack exchange,提问作者Chanky Mallick
相关产品推荐
相关产品推荐

