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

620 Views Asked by At

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!

1

There are 1 best solutions below

0
Maik Hasler On BEST ANSWER

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