Java使用BouncyCastle修改CSR的SubjectPublicKeyInfo OID,需仅留指定OID
解决CSR中SubjectPublicKeyInfo重复OID问题
你当前代码的问题在于:keyPair.getPublic().getEncoded()返回的是完整的X.509格式公钥编码,里面已经包含了公钥自身的AlgorithmIdentifier(也就是你说的“公钥自带OID”)。把这个完整编码塞进DERBitString后,构建的SubjectPublicKeyInfo就会同时包含你指定的OID,以及嵌套在公钥数据里的另一个OID,最终导致重复。
要只保留你指定的OID,必须提取公钥的原始数据部分(不含自带的AlgorithmIdentifier),再和指定的OID组合成SubjectPublicKeyInfo。以下是针对不同公钥类型的修正代码:
情况1:RSA公钥
// 假设keyPair.getPublic()是RSAPublicKey类型 RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); // 将RSA公钥参数转换为ASN.1结构 RSAPublicKeyStructure rsaStruct = new RSAPublicKeyStructure(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent()); // 提取纯公钥数据的DER编码 ASN1Primitive rsaDer = rsaStruct.toASN1Primitive(); ASN1BitString publicKeyData = new DERBitString(rsaDer.getEncoded()); // 指定自定义OID ASN1ObjectIdentifier customOid = new ASN1ObjectIdentifier("你的指定OID"); AlgorithmIdentifier customAlgId = new AlgorithmIdentifier(customOid); // 构建正确的SubjectPublicKeyInfo SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(customAlgId, publicKeyData); // 后续构建CSR的逻辑不变 PKCS10CertificationRequestBuilder csrBuilder = new PKCS10CertificationRequestBuilder( X500Name.getInstance(AsnToDerEncoding.createSubject()), subjectPublicKeyInfo );
情况2:EC(椭圆曲线)公钥
// 假设keyPair.getPublic()是ECPublicKey类型 ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic(); // 提取EC点的编码(不含算法标识) byte[] ecPointBytes = ecPublicKey.getQ().getEncoded(false); // false表示不带压缩标记,按需调整 ASN1BitString publicKeyData = new DERBitString(ecPointBytes); // 指定自定义OID ASN1ObjectIdentifier customOid = new ASN1ObjectIdentifier("你的指定OID"); AlgorithmIdentifier customAlgId = new AlgorithmIdentifier(customOid); // 构建正确的SubjectPublicKeyInfo SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(customAlgId, publicKeyData); // 后续构建CSR的逻辑不变 PKCS10CertificationRequestBuilder csrBuilder = new PKCS10CertificationRequestBuilder( X500Name.getInstance(AsnToDerEncoding.createSubject()), subjectPublicKeyInfo );
核心逻辑说明
- 关键是拆分公钥结构:把公钥的算法标识和原始数据分开,用你指定的OID替换默认的算法标识,再和纯数据组合。
- 不同类型的公钥(RSA/EC/DSA等)提取原始数据的方式不同,需要根据实际公钥类型做对应处理。
内容的提问来源于stack exchange,提问作者Gaurav Vaishnav
相关产品推荐
相关产品推荐

