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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:35:28