Search code examples
c#encodingasn.1der

How to write a complex ASN.1 sequence in C#?


I need to build an ASN.1 DER sequence for my digitial signature. The sequence is described in the following. My problem is the inner sequences, like encapContentInfo, since I don't know how to add those inner sequences in my SignedData sequence.

SignedData ::= SEQUENCE {
 version CMSVersion,
 digestAlgorithms DigestAlgorithmIdentifiers,
 encapContentInfo EncapsulatedContentInfo,
 certificates [0] IMPLICIT CertificateSet OPTIONAL,
 crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
 signerInfos SignerInfos }

where

EncapsulatedContentInfo ::= SEQUENCE {
 eContentType ContentType,
 eContent [0] EXPLICIT OCTET STRING OPTIONAL }

Right now, I am writing the ASN.1 like this:

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);

My guess would be to write the inner sequence first and then write it to the outer sequence. Nevertheless, I don't know if this is the correct way and how to implement it exactly.

So my question is: "Does anybody know how I could write this complex sequence?". I highly appreciate any kind of help or suggestion, cheers!


Solution

  • My first intention was right. I first have to write and encode the inner sequence and add the value to the outer sequence, like shown below.

    public void CreateSequenceOfTypeSignedData()
    {
        var writer = new AsnWriter(AsnEncodingRules.DER);
    
        using (writer.PushSequence())
        {
            writer.WriteInteger(1);
    
            writer.WriteObjectIdentifier("2.16.840.1.101.3.4.2.1");
    
            writer.WriteEncodedValue(CreateSequenceOfTypeEncapContentInfo());
        }
    
        var value = writer.Encode();
    
        Console.WriteLine(Convert.ToBase64String(value));
    }
    
    public byte[] CreateSequenceOfTypeEncapContentInfo()
    {
        var writer = new AsnWriter(AsnEncodingRules.DER);
    
        using (writer.PushSequence())
        {
            writer.WriteObjectIdentifier("1.2.840.113549.1.7.1");
        }
    
        return writer.Encode();
    }
    

    The above returns the following base64 string...

    MBsCAQEGCWCGSAFlAwQCATALBgkqhkiG9w0BBwE=
    

    ... which can be decoded into the following using this online ASN.1 JavaScript decoder. enter image description here