Bouncy Castle如何添加SerialNumber、UID为SAN扩展
问题原因
报错来自两处代码写法错误:
- 常量使用错误:
X509Name.SerialNumber、X509Name.UID是X.500主题可分辨名称(DN)的字段OID常量,不是SAN(主题备用名称)中GeneralName的合法类型标签,错用这两个值会让GeneralName构造函数匹配到要求整数入参的重载,触发string转int的类型错误。 - 扩展参数格式错误:
certGen.AddExtension的第三个参数仅接受单个ASN.1编码对象,不能直接传入多个GeneralName实例,必须先把所有SAN条目封装为GeneralNames类型的集合对象。
另外需要注意:RFC 5280标准定义的SAN内置类型没有直接对应SerialNumber、UID的标签,这类自定义字符串属性需要用otherName类型封装,绑定对应字段的OID后传入。
正确实现代码
以下是基于BouncyCastle库的可运行写法,字符串值可以正常传入:
// 构造DNS类型SAN条目 GeneralName dnsEntry = new GeneralName(GeneralName.DnsName, "bc1.local"); // 构造序列号SAN条目:使用otherName类型,绑定序列号OID 2.5.4.5,值用UTF8字符串封装 OtherName snEntry = new OtherName( X509Name.SerialNumber, new DerUtf8String("1234567890") ); GeneralName snName = new GeneralName(GeneralName.OtherName, snEntry); // 构造UID SAN条目:使用otherName类型,绑定UID OID 0.9.2342.19200300.100.1.1,值用UTF8字符串封装 OtherName uidEntry = new OtherName( X509Name.UID, new DerUtf8String("123456789123456") ); GeneralName uidName = new GeneralName(GeneralName.OtherName, uidEntry); // 所有条目封装为GeneralNames集合后传入扩展 GeneralNames sanEntries = new GeneralNames(new [] { dnsEntry, snName, uidName }); certGen.AddExtension(X509Extensions.SubjectAlternativeName, false, sanEntries);
补充说明
如果你的业务场景要求把SerialNumber、UID作为目录名(directoryName)的组成部分而非自定义otherName,可以自行构造X509Name对象,用GeneralName.DirectoryName标签生成条目加入集合即可,上述otherName写法适用于绝大多数CA对CSR中自定义字符串SAN字段的校验要求。
内容的提问来源于stack exchange,提问作者MK Said
相关产品推荐
相关产品推荐

