2

.NET's System.DirectoryServices.Protocols assembly specifies a light-weight ASN.1 BER encoder, but the documentation is not great: BerConverter.

You call it by specifying a format string and a list of objects to encode.

  • INTEGERs can be encoded with format characters i or e
  • OCTET STRINGs can be encoded with o character
  • SEQUENCEs can be encoded with { and }
  • etc.

I'd really like to make use of this simple converter so I don't have to take on an additional dependency. Taking on a dependency is undesirable because C# is callable from Powershell, and it is great to distribute a script that does something fancy with C# so long as it doesn't require an assembly that isn't included with .NET.

However, BerConverter doesn't seem to have a way to specify an Application or Context-Specific tag, which are often used to remove ambiguity in ASN.1, for example when components of a constructed type are marked as OPTIONAL

So, I can encode the following:

BerConverter.Encode("{i{i}}", 1, 2);

Which gives:

30 84 00 00 00 0c 02 01 01 30 84 00 00 00 03 02 01 02

But, if that second sequence needs to be [Application 1] or 61... I'm not sure what to put in the format string to emit that in the encoding.

Does BerConverter even have this capability?

petrsnd
  • 6,046
  • 5
  • 25
  • 34
  • 1
    You could try to use a decompiler (e.g. ILSpy) and look in the BerConverter code to see what it does. – Andrei Bozantan Oct 28 '16 at 12:12
  • @bosonix Thanks for the comment. I don't know why I didn't think to decompile. I used JetBrains dotPeek to decompile `BerConverter.Encode()`, and I found out that it is calling `ber_printf()` under the covers. It has better documentation. See answer below. – petrsnd Oct 28 '16 at 14:57

1 Answers1

1

I'm not sure why I didn't just do this up front, but I used a decompiler to look at the code. I found that BerConverter.Encode() is based on ber_printf(), which has much better documentation.

From the docs:

Character: 't'

Description:

Tag. The next argument is a ber_tag_t that specifies the tag to override the next element written to the BerElement. This works across calls.

So, I was able to change my code to:

BerConverter.Encode("{it{i}}", 1, 0x61, 2)

Which allows me to set the tag value to 0x61 and the code emits:

30 84 00 00 00 0c 02 01 01 61 84 00 00 00 03 02 01 02

Community
  • 1
  • 1
petrsnd
  • 6,046
  • 5
  • 25
  • 34