- Author: Jonathan M. Wilbur <jonathan@wilbur.space>
- Copyright Year: 2018
- License: MIT License
- Version: See
version
file or git tags.
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.
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
.
ASN.1 is used in, or required by, multiple technologies, including:
- X.509 Certificates, used in SSL/TLS
- Lightweight Directory Access Protocol (LDAP)
- X.400, the messaging system used by the U.S. Military
- X.500
- The magnetic stripes on credit cards and debit cards
- Microsoft's Remote Desktop Protocol (RDP)
- Simple Network Management Protocol (SNMP)
- Common Management Information Protocol (CMIP)
- Signalling System Number 7 (SS7), used to make most phone calls on the Public Switched Telephone Network (PSTN).
- Kerberos 5
- H.323 Video conferencing
- Biometrics Protocols:
- Computer Supported Telecommunications Applications (CSTA)
- Dedicated Short Range Communications (SAE J2735)
- Cellular telephony:
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
.
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:
- Let me know why. If you have good ideas, I will be more than happy to implement them in this library.
- 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.
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
.
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.
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.
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.
The codecs are intended to be final
classes, but due to
this bug I found, they cannot
be final
until that bug is resolved.
- Ilya Tingof (@etingof), who answered several questions of mine on StackOverflow, and who authored PyASN1.
- @YuryStrozhevsky for his ASN.1 BER Codec and his @YuryStrozhevsky's ASN.1 Test Suite
- X.680 - Abstract Syntax Notation One (ASN.1), published by the International Telecommunications Union.
- X.690 - ASN.1 encoding rules, published by the International Telecommunications Union.
- ASN.1: Communication Between Heterogeneous Systems by Olivier Dubuisson
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). 🐗