Reputation: 553
Since June 2020 .net has a an ASN1 reader implemented. In the documentation there is no example how to use it. Also a search at Google and in SO doesn't show any examples or descriptions. Where can I find some?
Upvotes: 11
Views: 4604
Reputation: 553
I found the design document at Microsoft (very well hidden) with some examples. And kudos to Karl-Johan who found the related unit tests. Based on these examples, I was able to write a comprehensive example program which parses an OCSP response.
using System.Formats.Asn1;
// An OCSP response according https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 as Base64 encoded DER
string b64OCSPResponseDER = @"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";
byte[] ocspResponseDER = Convert.FromBase64String(b64OCSPResponseDER);
AsnReader asnReader1 = new(new ReadOnlyMemory<byte>(ocspResponseDER), AsnEncodingRules.DER);
AsnReader? ocspResponse = asnReader1.ReadSequence();
OCSPResponseStatus? responseStatus = ocspResponse?.ReadEnumeratedValue<OCSPResponseStatus>();
Asn1Tag context0 = new (TagClass.ContextSpecific, 0);
AsnReader? responseBytes = ocspResponse?.ReadSequence(context0);
AsnReader? _responseBytes = responseBytes?.ReadSequence();
string? responseType = _responseBytes?.ReadObjectIdentifier();
byte[]? response = _responseBytes?.ReadOctetString();
AsnReader asnReader2 = new(new ReadOnlyMemory<byte>(response), AsnEncodingRules.DER);
AsnReader? basicOCSPResponse = asnReader2.ReadSequence();
AsnReader? tbsResponseData = basicOCSPResponse?.ReadSequence();
// Skip parsing of tbsResponseData
AsnReader? signatureAlgorithm = basicOCSPResponse?.ReadSequence();
// Skip parsing of signatureAlgorithm
int unusedBitsCounter;
byte[]? signature = basicOCSPResponse?.ReadBitString(out unusedBitsCounter);
AsnReader? certs = basicOCSPResponse?.ReadSequence(context0);
AsnReader? cert1 = certs?.ReadSequence();
ReadOnlyMemory<byte> encodedValue = cert1.ReadEncodedValue();
string b64encodedCert1 = Convert.ToBase64String(encodedValue.ToArray());
bool endReached = !certs.HasData;
Console.WriteLine(b64encodedCert1);
enum OCSPResponseStatus : byte
{
successful = 0, // Response has valid confirmations
malformedRequest = 1, // Illegal confirmation request
internalError = 2, // Internal error in issuer
tryLater = 3, // Try again later
// (4) is not used
sigRequired = 5, // Must sign the request
unauthorized = 6 // --Request unauthorized
}
Upvotes: 12