Java 17下基于Bouncycastle从PEM格式RSA公钥生成Key对象方案
兼容Java 17的RSA公钥转Java Key对象方案(基于Bouncycastle)
原代码依赖的sun.security.util.DerInputStream和DerValue属于JDK内部API,Java 9起被标记为禁用,以下是基于Bouncycastle库的替代实现,完全兼容Java 17+。
方案一:对齐原代码逻辑的手动解析
这种方式和你原代码的解析逻辑一致,只是替换为Bouncycastle的公开ASN.1解析类:
import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.pkcs.RSAPublicKey; import java.math.BigInteger; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; // ... 业务代码 String keyData = r.getPublicKey() .replace("-----BEGIN RSA PUBLIC KEY-----", "") .replace("-----END RSA PUBLIC KEY-----", "") .replaceAll("\\s+", ""); // 清理所有空白字符,避免解析异常 byte[] content = Base64.getDecoder().decode(keyData); try (ASN1InputStream asn1InputStream = new ASN1InputStream(content)) { // 直接用Bouncycastle的RSAPublicKey类解析PKCS#1格式的公钥 RSAPublicKey rsaPublicKey = RSAPublicKey.getInstance(asn1InputStream.readObject()); BigInteger modulus = rsaPublicKey.getModulus(); BigInteger publicExp = rsaPublicKey.getPublicExponent(); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExp); PublicKey pk = kf.generatePublic(keySpec); // 使用生成的公钥pk } catch (Exception e) { throw new RuntimeException("解析RSA公钥失败", e); }
方案二:更简洁的PEM直接读取
利用Bouncycastle的PEMParser可以直接处理带头的PEM格式公钥,省去手动替换头和Base64解码的步骤:
import org.bouncycastle.asn1.pkcs.RSAPublicKey; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.openssl.PEMParser; import java.io.StringReader; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.RSAPublicKeySpec; import java.security.spec.X509EncodedKeySpec; // ... 业务代码 String publicKeyStr = r.getPublicKey(); try (StringReader reader = new StringReader(publicKeyStr); PEMParser pemParser = new PEMParser(reader)) { Object pemObject = pemParser.readObject(); PublicKey pk; KeyFactory kf = KeyFactory.getInstance("RSA"); if (pemObject instanceof SubjectPublicKeyInfo) { // 处理X.509格式公钥(BEGIN PUBLIC KEY) SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) pemObject; pk = kf.generatePublic(new X509EncodedKeySpec(spki.getEncoded())); } else if (pemObject instanceof RSAPublicKey) { // 处理PKCS#1格式公钥(BEGIN RSA PUBLIC KEY) RSAPublicKey rsaPublicKey = (RSAPublicKey) pemObject; pk = kf.generatePublic(new RSAPublicKeySpec(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent())); } else { throw new IllegalArgumentException("不支持的公钥格式"); } // 使用生成的公钥pk } catch (Exception e) { throw new RuntimeException("解析RSA公钥失败", e); }
核心替换点
- 原
sun.security.util.DerInputStream→org.bouncycastle.asn1.ASN1InputStream - 原手动解析DER序列 → 直接用
org.bouncycastle.asn1.pkcs.RSAPublicKey封装解析逻辑,减少出错概率 - 方案二的
PEMParser支持直接读取标准PEM格式,代码更简洁健壮
内容的提问来源于stack exchange,提问作者jnasworld223
相关产品推荐
相关产品推荐

