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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:57:17