You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:42:23