如何修改Bouncy Castle代码生成与OpenSSL一致的命名曲线CSR
Bouncy Castle生成与OpenSSL一致的EC CSR修改方案
以下是针对差异点的具体修改项,覆盖公钥编码、签名算法、字段顺序、扩展编码等核心对齐点:
1. 公钥使用命名曲线编码(而非显式参数)
OpenSSL生成EC CSR时,公钥默认通过命名曲线OID标识参数,而Bouncy Castle默认可能输出显式曲线参数。需修改公钥生成逻辑,强制使用命名曲线格式:
// 替换原公钥获取代码,生成带命名曲线标识的公钥参数 var curveOid = curve.Oid; var publicKey = new ECPublicKeyParameters( "ECDSA", keyPair.Public.Q, curveOid );
2. 签名算法OID与OpenSSL对齐
OpenSSL的SHA256withECDSA对应标准OID 1.2.840.10045.4.3.2,需明确指定该OID创建签名工厂:
// 使用标准OID创建签名工厂,匹配OpenSSL签名算法标识 var signatureFactory = new Asn1SignatureFactory( "1.2.840.10045.4.3.2", keyPair.Private, secureRandom );
3. 固定Subject DN字段顺序
Hashtable的键枚举是无序的,而OpenSSL的Subject DN字段顺序由命令行指定顺序决定,需手动指定字段顺序:
// 明确Subject DN字段顺序,匹配OpenSSL输出 var subjectAttrKeys = new ArrayList { X509Name.C, X509Name.O, X509Name.OU, X509Name.CN }; var subjectName = new X509Name(subjectAttrKeys, subjectAttributes);
4. 固定Subject Alternative Name字段顺序
同理,Subject Alternative Name中的目录名字段顺序需手动指定,避免Hashtable的无序问题:
// 明确Subject Alternative Name字段顺序 var sanAttrKeys = new ArrayList { X509Name.Surname, X509Name.UID, X509Name.T, RegisteredAddress, X509Name.BusinessCategory }; var subjectAltNames = new X509Name(sanAttrKeys, subjectAlternativeNameAttributes);
5. 调整Microsoft证书模板扩展编码
OpenSSL中该扩展通常直接编码模板名称的UTF-8字节,替换原DisplayText方式:
// 改为直接编码模板名称字节,匹配OpenSSL扩展格式 byte[] templateBytes = Encoding.UTF8.GetBytes("Test-Signing"); extensionsGenerator.AddExtension(MicrosoftObjectIdentifiers.MicrosoftCertTemplateV1, false, new DerOctetString(templateBytes));
完整修改后代码
var curve = ECNamedCurveTable.GetByName("secp256k1"); var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed()); var secureRandom = new SecureRandom(); var keyParams = new ECKeyGenerationParameters(domainParams, secureRandom); var generator = new ECKeyPairGenerator("ECDSA"); generator.Init(keyParams); var keyPair = generator.GenerateKeyPair(); // 带命名曲线标识的公钥参数 var curveOid = curve.Oid; var publicKey = new ECPublicKeyParameters( "ECDSA", keyPair.Public.Q, curveOid ); IDictionary subjectAttributes = new Hashtable(); subjectAttributes.Add(X509Name.CN, "Test1"); subjectAttributes.Add(X509Name.O, "Test2"); subjectAttributes.Add(X509Name.OU, "Test3"); subjectAttributes.Add(X509Name.C, "SA"); DerObjectIdentifier RegisteredAddress = new DerObjectIdentifier("2.5.4.26"); IDictionary subjectAlternativeNameAttributes = new Hashtable(); subjectAlternativeNameAttributes.Add(X509Name.Surname, "TestSN"); subjectAlternativeNameAttributes.Add(X509Name.UID, "010101010101010"); subjectAlternativeNameAttributes.Add(X509Name.T, "1100"); subjectAlternativeNameAttributes.Add(RegisteredAddress, "Test Address"); subjectAlternativeNameAttributes.Add(X509Name.BusinessCategory, "IT"); // 固定Subject DN字段顺序 var subjectAttrKeys = new ArrayList { X509Name.C, X509Name.O, X509Name.OU, X509Name.CN }; var subjectName = new X509Name(subjectAttrKeys, subjectAttributes); // 固定Subject Alternative Name字段顺序 var sanAttrKeys = new ArrayList { X509Name.Surname, X509Name.UID, X509Name.T, RegisteredAddress, X509Name.BusinessCategory }; var subjectAltNames = new X509Name(sanAttrKeys, subjectAlternativeNameAttributes); var generalNames = new GeneralNames(new[] { new GeneralName(subjectAltNames) }); var extensionsGenerator = new X509ExtensionsGenerator(); // 调整Microsoft证书模板扩展编码 byte[] templateBytes = Encoding.UTF8.GetBytes("Test-Signing"); extensionsGenerator.AddExtension(MicrosoftObjectIdentifiers.MicrosoftCertTemplateV1, false, new DerOctetString(templateBytes)); extensionsGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, generalNames); var extensions = extensionsGenerator.Generate(); // 使用标准OID创建签名工厂 var signatureFactory = new Asn1SignatureFactory( "1.2.840.10045.4.3.2", keyPair.Private, secureRandom ); var attributes = new AttributeX509(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(extensions)); var requestAttributeSet = new DerSet(attributes); var certificateRequest = new Pkcs10CertificationRequest(signatureFactory, subjectName, publicKey, requestAttributeSet);
内容的提问来源于stack exchange,提问作者WL1985
相关产品推荐
相关产品推荐

