fASN1.NET 1.3.0

dotnet add package fASN1.NET --version 1.3.0                
NuGet\Install-Package fASN1.NET -Version 1.3.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="fASN1.NET" Version="1.3.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add fASN1.NET --version 1.3.0                
#r "nuget: fASN1.NET, 1.3.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install fASN1.NET as a Cake Addin
#addin nuget:?package=fASN1.NET&version=1.3.0

// Install fASN1.NET as a Cake Tool
#tool nuget:?package=fASN1.NET&version=1.3.0                

fASN1.NET

Nuget MIT License

fASN1.NET is a .NET library for working with ASN.1 (Abstract Syntax Notation One) data. It provides functionality for serializing and deserializing ASN.1 data, as well as extracting various pieces of information from ASN.1 encoded certificates.

Features

  • Serialize and deserialize ASN.1 data.
  • ASN.1 data structured string representation.
  • Extract key usage, extended key usage, SAN (Subject Alternative Name), and other certificate details.
  • Support for long string content handling, including wrapping and word wrapping.

ASN.1 references

Table of Contents

Installation

fASN1.NET is available as a NuGet package. You can install it using the following command:

dotnet add package fASN1.NET

Usage

Deserialize ASN.1 Data and get certificate details

The main purpose of the library is to work with ASN.1 encoded certificates. The following example demonstrates how to deserialize an ASN.1 encoded certificate and extract various pieces of information from it.

using System;
using System.Collections.Generic;
using System.IO;
using fASN1.NET;

//current github ssl cert (as of 04.08.2024)
var data = Convert.FromBase64String("MIIEozCCBEmgAwIBAgIQTij3hrZsGjuULNLEDrdCpTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIEVDQyBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMB4XDTI0MDMwNzAwMDAwMFoXDTI1MDMwNzIzNTk1OVowFTETMBEGA1UEAxMKZ2l0aHViLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABARO/Ho9XdkY1qh9mAgjOUkWmXTb05jgRulKciMVBuKB3ZHexvCdyoiCRHEMBfFXoZhWkQVMogNLo/lW215X3pGjggL+MIIC+jAfBgNVHSMEGDAWgBT2hQo7EYbhBH0Oqgss0u7MZHt7rjAdBgNVHQ4EFgQUO2g/NDr1RzTK76ZOPZq9Xm56zJ8wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEkGA1UdIARCMEAwNAYLKwYBBAGyMQECAgcwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQIBMIGEBggrBgEFBQcBAQR4MHYwTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMIIBgAYKKwYBBAHWeQIEAgSCAXAEggFsAWoAdwDPEVbu1S58r/OHW9lpLpvpGnFnSrAX7KwB0lt3zsw7CAAAAY4WOvAZAAAEAwBIMEYCIQD7oNz/2oO8VGaWWrqrsBQBzQH0hRhMLm11oeMpg1fNawIhAKWc0q7Z+mxDVYV/6ov7f/i0H/aAcHSCIi/QJcECraOpAHYAouMK5EXvva2bfjjtR2d3U9eCW4SU1yteGyzEuVCkR+cAAAGOFjrv+AAABAMARzBFAiEAyupEIVAMk0c8BVVpF0QbisfoEwy5xJQKQOe8EvMU4W8CIGAIIuzjxBFlHpkqcsa7UZy24y/B6xZnktUw/Ne5q5hCAHcATnWjJ1yaEMM4W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGOFjrv9wAABAMASDBGAiEA+8OvQzpgRf31uLBsCE8ktCUfvsiRT7zWSqeXliA09TUCIQDcB7Xn97aEDMBKXIbdm5KZ9GjvRyoF9skD5/4GneoMWzAlBgNVHREEHjAcggpnaXRodWIuY29tgg53d3cuZ2l0aHViLmNvbTAKBggqhkjOPQQDAgNIADBFAiEAru2McPr0eNwcWNuDEY0a/rGzXRfRrm+6XfZeSzhYZewCIBq4TUEBCgapv7xvAtRKdVdi/b4m36Uyej1ggyJsiesA");

using var ms = new MemoryStream(data);
var tag = Asn1Serializer.Deserialize(ms);

if (Asn1Serializer.TryDeserialize(data, out var tag2, out var error) is false)
{
    Console.WriteLine($"Data deserialization error: {error}");
    return;
}

if (tag.TryGetCertificateSubjectItem(SubjectItemKind.CommonName, true, out List<string> issuerCn))
{
    Console.WriteLine($"Issuer CN: {issuerCn[0]}");
}

if (tag.TryGetCertificateSubjectItem(SubjectItemKind.CommonName, false, out List<string> subjectCn))
{
    Console.WriteLine($"Subject CN: {subjectCn[0]}");
}

if(tag.TryGetCertificateNotAfter(out var notAfter))
{
    Console.WriteLine($"Not After: {notAfter}");
}

if (tag.TryGetKeyUsage(out var ku))
{
    Console.WriteLine($"Key Usage: {ku}");
}

Output:

Issuer CN: Sectigo ECC Domain Validation Secure Server CA
Subject CN: github.com
Not After: 07.03.2025 23:59:59
Key Usage: DigitalSignature, NonRepudiation

Serialize ASN.1 Data

This library also provides functionality for serializing ASN.1 data. The following example demonstrates how to serialize an ASN.1 tag.

using System;
using System.Text;
using fASN1.NET;
using fASN1.NET.Tags;

var root = new Sequence([
    new Integer([1]),
    new Sequence([
        new ObjectIdentifier([0,1,35,45,55,127,126]),
        new Utf8String(Encoding.UTF8.GetBytes("Random text")),
        new ContextSpecific_0(children: [
            new BitString(content: [123,125,222,255,0,1,4])
            ])
    ])
]);

var serialized = Asn1Serializer.Serialize(root);
var deserializedTag = Asn1Serializer.Deserialize(serialized);
var deserializedText = Asn1Serializer.TagToString(deserializedTag);
Console.WriteLine(deserializedText);

The data looks like this after serialization into a string:

Sequence
 | Integer 1
 | Sequence
 |  | ObjectIdentifier 0.0.1.35.45.55.127.126
 |  | UTF8String Random text
 |  | [0]
 |  |  | BitString 011110110111110111011110111111110000000000000001000

Get Subject Director Attributes (SDA) from a certificate

The fASN1.NET library provides a predefined class for working with Subject Directory Attributes (SDA), as specified in (https://datatracker.ietf.org/doc/html/rfc3739#page-9).

The SubjectDirectoryAttributes class includes the following properties:

    /// <summary>
    /// Gets the gender. 
    /// </summary>
    /// <remarks>
    /// If this property is <see langword="null"/>, you may use <see cref="GenderString"/> property to get value that is not in the enum range.
    /// </remarks>
    public Gender? Gender { get; protected set; }

    /// <summary>
    /// Gets the gender as a string.
    /// </summary>
    public string? GenderString { get; protected set; }

    /// <summary>
    /// Gets the date of birth.
    /// </summary>
    public DateTime? DateOfBirth { get; protected set; }

    /// <summary>
    /// Gets the place of birth.
    /// </summary>
    public string? PlaceOfBirth { get; protected set; }

    /// <summary>
    /// Gets the country of residence.
    /// </summary>
    public IReadOnlyList<string> CountryOfResidence { get; protected set; }

    /// <summary>
    /// Gets the country of citizenship.
    /// </summary>
    public IReadOnlyList<string> CountryOfCitizenship { get; protected set; }

The SubjectDirectoryAttributes class is not sealed, allowing developers to inherit it to add custom properties or override setters for existing ones.

SubjectDirectoryAttributes class in the following file: SubjectDirectory/SubjectDirectoryAttributes.cs

The example below demonstrates how to extract Subject Directory Attributes (SDA) from an X.509v3 certificate:

ITag cert = new X509Certificate2(_pem);
bool sda = SubjectDirectoryAttributes.FromCertificate(cert);

You can also extract the Subject Directory Attributes (SDA) directly from an ASN.1 tag:

ITag tag = Asn1Serializer.Deserialize(_pem);
bool success = tag.TryGetSubjectDirectoryAttributesFromCertificate(out var sda);

Performance

The following table shows the performance of the current implementation when working with certificates.

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3880/23H2/2023Update/SunValley3)
AMD Ryzen 7 7840HS with Radeon 780M Graphics, 1 CPU, 16 logical and 8 physical cores
.NET SDK 8.0.300
  [Host]     : .NET 8.0.5 (8.0.524.21615), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
  DefaultJob : .NET 8.0.5 (8.0.524.21615), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Method Mean Error StdDev Gen0 Gen1 Allocated
DeserializeCertificate 4.846 us 0.0961 us 0.1733 us 2.0294 0.1068 16.61 KB
SerializeCertificateTagToString 50.612 us 0.3710 us 0.3470 us 10.9863 0.4883 90.45 KB

The previous version of the library (Asn1DecoderNet5) was like this:

Method Mean Error StdDev Gen0 Gen1 Allocated
DeserializeCertificate 27.93 us 0.105 us 0.088 us 2.7161 0.1526 22.23 KB
SerializeCertificateTagToString 89.47 us 1.723 us 1.527 us 46.6309 7.2021 381.05 KB

The performance has been significantly improved, especially when serializing the data to a string.

Note: The smaller and less complex the data, the better the performance (especially the memory allocation).

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.3.0 114 11/20/2024
1.2.1 120 9/28/2024
1.2.0 94 9/28/2024
1.1.0 141 8/18/2024
1.0.1 122 8/14/2024
1.0.0 118 8/11/2024