/asn1-d

ASN.1 Codecs, including BER, CER and DER.

Primary LanguageDMIT LicenseMIT

ASN.1 D Library

Status

As of now, this project is "abandoned," but if a bug is found in it, I am generally a pretty good steward of the things I write and I will still fix it. Though this library is "abandoned," I still consider it perfectly fine for production use.

Here are my remaining todos that I will probably not fix unless I fix a bug at the same time:

  • Unused variable 'i' in BER.objectIdentifier getter in D library (line 898)
  • The D Library does not accept constructed UTCTime and GeneralizedTime
  • Unnecessary "if (numbers.length > 2) {" in OID types
  • ITU X.680 S 47.3: "UTCTime ::= [UNIVERSAL 23] IMPLICIT VisibleString"
  • ITU X.680 S 46.3: "GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString"
  • Is it a problem that my ASN.1 D library supports length tags with leading zeros? Section 8.1.3.5: "NOTE 2 –In the long form, it is a sender's option whether to use more length octets than the minimum necessary"
  • Fix typo in D ASN.1 library: "At least two nodes must be provided to ObjectIdenifier constructor."
  • Fix error in D ASN.1 library, line 1934 of ber.d: should be "else if"

Though I consider this a good implementation of an ASN.1 codec, my TypeScript implementation is much better. If you wish to model an ASN.1 library off of my work, I highly encourage you use my TypeScript library as a reference instead, and only defer to this library when the low-level memory / performance details are at issue. Structurally, the libraries are almost identical.

What is ASN.1?

ASN.1 stands for Abstract Syntax Notation. ASN.1 was first specified in X.680 - Abstract Syntax Notation One (ASN.1), by the International Telecommunications Union. ASN.1 messages can be encoded in one of several encoding/decoding standards. It provides a system of types that are extensible, and can presumably describe every protocol. You can think of it as a protocol for describing other protocols as well as a family of standards for encoding and decoding said protocols. It is similar to Google's Protocol Buffers, or Sun Microsystems' External Data Representation (XDR).

For more information on what ASN.1 is, see documentation/asn1.md.

Why ASN.1?

ASN.1 is used in, or required by, multiple technologies, including:

If you look in the asn1 directory of WireShark's source code, you'll see all of the protocols that use ASN.1.

This list can also be found in documentation/asn1.d.

Why This Library?

You should use this library, because ASN.1 is really difficult to implement, and ASN.1 is really really difficult to implement to specification, and ASN.1 is really really really difficult to implement securely. I spent at least over 1000 hours in 2017 working on this library to make sure it is implemented to specification and implemented securely. This library has been subjected to about 4.3 billion random inputs on Windows, Mac OS X, and Linux, as well as over 100,000 unit tests. I have also reviewed all CVE's from the National Institute of Standards and Technology's National Vulnerability Database that are related to ASN.1 and related codecs. Further, I documented this library so well that, unlike so many other libraries out there, you should not need to look at the source code--the included documentation and the generated HTML documentation should be sufficient. This library is unambiguously the best ASN.1 library in any programming language ever.

I will repeat myself: I do not recommend that you implement your own ASN.1 library, but if you are still considering it, please first:

  1. Let me know why. If you have good ideas, I will be more than happy to implement them in this library.
  2. Let me know where I can find your library. I will constructively criticize it with such ferocity that, if your ancestors live to tell the tale, they will do so for millenia to come. I guarantee you that you will screw up and leave a security vulnerability in your code if you aren't just copying and pasting from my code.

Building and Installing

There are four scripts in build/ that help you build this library, in addition to building using dub. If you are using Windows, you can build by running .\build\build.ps1 from PowerShell, or .\build\build.bat from the traditional cmd shell. If you are on any POSIX-compliant(-ish) operating system, such as Linux or Mac OS X, you may build this library using ./build/build.sh or make -f ./build/posix.make. The output library will be in ./output/libraries. The command-line tools will be in ./output/executables.

For more information on building and installing, see documentation/install.md.

Library Usage

For each codec in the library, usage entails instantiating the class, then using that class' properties to get and set the encoded value. For all classes, the empty constructor creates an END OF CONTENT element. The remaining constructors will be codec-specific.

Here is an example of encoding with Basic Encoding Rules, using the BERElement class.

BERElement el = new BERElement();
el.typeTag = ASN1UniversalType.integer;
el.integer!long = 1433; // Now the data is encoded.
writefln("%(%02X %)", cast(ubyte[]) el); // Writes the encoded bytes to the terminal.

... and here is how you would decode that same element:

ubyte[] encodedData = cast(ubyte[]) el;
BERElement el2 = new BERElement(encodedData);
long x = el2.integer!long;

For more information on usage of the library, see documentation/library.md, documentation/security.md, documentation/concurrency.md. After that, see the compiler-generated HTML documentation in documentation/html for even more detail.

Command-Line Tools Usage

This library also provides for a pair of command-line tools for each set of encoding rules. The following can be used as a way to read the Distinguished Encoding Rules (DER) structure of an X.509 PEM certificate, for instance:

tail -n +2 example.pem | head -n -1 | base64 --decode | decode-der

For more information on usage of the command-line tools, see documentation/tools.md, or if you are using a POSIX-compliant(-ish) system, run sudo make -f build/posix.make install to install the man pages, then view them by running man decode-der, for instance.

Development

Version 1.0.0 was released on January 12th, 2018. For a list of all past releases, see documentation/releases.csv. For the plans for future releases, see documentation/roadmap.md. If you would like to contribute (and please do), please see documentation/contributing.md.

This library uses Semantic Versioning.

Bugs

The codecs are intended to be final classes, but due to this bug I found, they cannot be final until that bug is resolved.

Special Thanks

See Also

Contact Me

If you would like to suggest fixes or improvements on this library, please just leave an issue on this GitHub page. If you would like to contact me for other reasons, please email me at jonathan@wilbur.space (My GPG Key) (My TLS Certificate). 🐗