如何在C#中编写含嵌套序列的ASN.1 DER SignedData?
构建ASN.1 DER格式SignedData序列:添加嵌套的encapContentInfo
我需要构建符合ASN.1定义的SignedData序列,当前卡在如何添加内层嵌套的encapContentInfo序列。
SignedData的ASN.1定义
SignedData ::= SEQUENCE { version CMSVersion, digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncapsulatedContentInfo, certificates [0] IMPLICIT CertificateSet OPTIONAL, crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, signerInfos SignerInfos }
EncapsulatedContentInfo的ASN.1定义
EncapsulatedContentInfo ::= SEQUENCE { eContentType ContentType, eContent [0] EXPLICIT OCTET STRING OPTIONAL }
我当前的C#代码
var writer = new AsnWriter(AsnEncodingRules.DER); using (writer.PushSequence()) { writer.WriteInteger(1, new Asn1Tag(TagClass.ContextSpecific, 0)); writer.WriteObjectIdentifier("2.16.840.1.101.3.4.2.1", new Asn1Tag(TagClass.ContextSpecific, 1)); // How do I add the inner sequence of type `encapContentInfo` here? } var extension = new X509Extension("1.2.840.113549.1.7.2", writer.Encode(), critical: false);
我猜测应先编写内层序列再写入外层,但不确定这是否正确,也不清楚具体实现方式,希望得到帮助或建议。
解决方案:嵌套使用PushSequence()
不需要单独提前构建内层序列,直接在SignedData的外层序列范围内,通过PushSequence()开启encapContentInfo的内层序列,写完字段后由using块自动闭合即可,AsnWriter会自动处理嵌套的DER编码逻辑。
修正后的完整代码示例
var writer = new AsnWriter(AsnEncodingRules.DER); // 开启外层SignedData序列 using (writer.PushSequence()) { // 1. version字段:CMSVersion类型,此处写版本1 writer.WriteInteger(1); // 注意:原代码的ContextSpecific标签错误,该字段无上下文标签 // 2. digestAlgorithms字段:SEQUENCE OF DigestAlgorithmIdentifier using (writer.PushSequence()) // 算法列表的外层序列 { using (writer.PushSequence()) // 单个DigestAlgorithmIdentifier序列 { writer.WriteObjectIdentifier("2.16.840.1.101.3.4.2.1"); // SHA256算法OID writer.WriteNull(); // SHA256无算法参数,写NULL } } // 3. 嵌套的encapContentInfo序列 using (writer.PushSequence()) // 开启EncapsulatedContentInfo序列 { // 3.1 eContentType:内容类型OID,示例用普通数据类型OID writer.WriteObjectIdentifier("1.2.840.113549.1.7.1"); // 3.2 可选的eContent字段:带[0] EXPLICIT标签 var contentBytes = Encoding.UTF8.GetBytes("需要封装的内容"); writer.WriteOctetString(contentBytes, new Asn1Tag(TagClass.ContextSpecific, 0, true)); // true表示EXPLICIT标签 } // 后续可按需添加certificates、crls、signerInfos字段,此处省略示例 } var extension = new X509Extension("1.2.840.113549.1.7.2", writer.Encode(), critical: false);
关键注意点
- 原代码中给version和digestAlgorithms添加ContextSpecific标签是错误的,SignedData定义里这两个字段是普通SEQUENCE成员,仅certificates、crls字段带[0][1]的IMPLICIT标签。
- digestAlgorithms是
SEQUENCE OF DigestAlgorithmIdentifier,需要嵌套两层序列:外层是算法列表,内层是单个算法的OID+参数。 - eContent字段的标签是
[0] EXPLICIT,写入时需指定Asn1Tag的isExplicit参数为true。
内容的提问来源于stack exchange,提问作者Maik Hasler
相关产品推荐
相关产品推荐

