ddn.crypto.encoding.asn1
ASN.1/DER encoding and decoding infrastructure.
Provides types and utilities for encoding and decoding data using Distinguished Encoding Rules (DER), a canonical subset of the Basic Encoding Rules (BER) for ASN.1.
Copyright
Types 6
ASN.1 tag class values.
The tag class occupies the two most significant bits of the tag byte.
ASN.1 universal tag numbers.
These identify the data type within the UNIVERSAL class.
Represents an ASN.1 tag (class + constructed flag + tag number).
For simplicity, only single-byte tag encoding is supported (tag numbers 0–30), which covers all common cryptographic use cases.
Asn1TagClass tagClassThe tag class (UNIVERSAL, APPLICATION, CONTEXT, or PRIVATE).ubyte tagNumberThe tag number within the class.bool constructedWhether the value is constructed (contains child TLVs).Asn1Tag sequence() pure nothrow @nogc @safeReturns a SEQUENCE tag (UNIVERSAL, constructed, number 0x10).Asn1Tag integer() pure nothrow @nogc @safeReturns an INTEGER tag (UNIVERSAL, primitive, number 0x02).Asn1Tag bitString() pure nothrow @nogc @safeReturns a BIT STRING tag (UNIVERSAL, primitive, number 0x03).Asn1Tag octetString() pure nothrow @nogc @safeReturns an OCTET STRING tag (UNIVERSAL, primitive, number 0x04).Asn1Tag contextTag(ubyte number, bool constructed = false) pure nothrow @nogc @safeCreates a context-specific tag with the given number.A TLV (Tag-Length-Value) container for ASN.1 data.
For primitive types, content holds the raw value bytes. For constructed types, content holds the concatenation of the encoded child TLVs.
Asn1Tag tagThe ASN.1 tag identifying the type and structure.ubyte[] contentThe value bytes (or encoded children for constructed types).Asn1Value sequence(ubyte[] content) pure @safeCreates a SEQUENCE Asn1Value with the given encoded child content.Asn1Value integer(ubyte[] content) pure @safeCreates an INTEGER Asn1Value with the given signed big-endian content.Asn1Value bitString(ubyte[] content, ubyte unusedBits = 0) pure @safeCreates a BIT STRING Asn1Value.A builder for constructing DER-encoded ASN.1 structures.
Use the save / wrapSequence / wrapContext pattern to build constructed values:
auto w = new DerWriter();
w.writeInteger(1);
w.writeOctetString([0x01, 0x02]);
auto pos = w.save();
w.wrapSequence(pos);
// buffer now holds SEQUENCE { INTEGER 1, OCTET STRING 0102 }ubyte[] _bufferubyte[] wrapTlv(Asn1Tag tag, const(ubyte)[] content) pure @safeWraps `content` in a TLV with the given tag.void writeInteger(const(ubyte)[] value)Writes a DER-encoded INTEGER from raw signed big-endian bytes.void writeInteger(long value)Writes a DER-encoded INTEGER from a signed `long` value.void writeOctetString(const(ubyte)[] value)Writes a DER-encoded OCTET STRING.void writeBitString(const(ubyte)[] value, ubyte unusedBits = 0)Writes a DER-encoded BIT STRING.void writeNull()Writes a DER-encoded NULL value (zero-length content).void writeOid(const(ubyte)[] encodedOid)Writes a DER-encoded OID.void writeBoolean(bool value)Writes a DER-encoded BOOLEAN.void writeRaw(Asn1Tag tag, const(ubyte)[] content)Writes a raw TLV with an explicit tag and content.void wrapSequence(size_t startPos)Wraps all bytes written since `startPos` in a SEQUENCE TLV.void wrapContext(size_t startPos, ubyte tagNumber)Wraps all bytes written since `startPos` in a context-tagged TLV.this()Constructs an empty DerWriter.Reads DER-encoded TLV values from a byte buffer.
Example:
auto reader = DerReader(encodedBytes);
auto seq = reader.enterSequence();
auto intBytes = seq.readInteger();
auto octets = seq.readOctetString();const(ubyte)[] _datasize_t _posubyte[] readInteger()Reads a DER INTEGER and returns its raw content bytes (signed, big-endian).ubyte[] readOctetString()Reads a DER OCTET STRING and returns its content bytes.ubyte[] readBitString(out ubyte unusedBits)Reads a DER BIT STRING and returns its data bytes.void readNull()Reads and verifies a DER NULL value.ubyte[] readOid()Reads a DER OID and returns its binary content bytes.bool readBoolean()Reads a DER BOOLEAN.DerReader enterConstructed(Asn1Tag expectedTag)Reads a constructed TLV with the expected tag and returns a new `DerReader` positioned over its content.DerReader enterSequence()Enters a SEQUENCE, returning a reader over its content.DerReader enterContext(ubyte tagNumber)Enters a constructed context-tagged TLV, returning a reader over its content.void skip()Skips the next complete TLV value.this(const(ubyte)[] data)Constructs a reader over the given DER-encoded data.Functions 10
ubyte[] derEncodeLength(size_t length) pure @safeEncodes a length value using DER length encoding.size_t derDecodeLength(const(ubyte)[] data, out size_t bytesRead)Decodes a DER-encoded length from the start of a byte buffer.ubyte[] encodeUnsignedInteger(const(ubyte)[] bigEndianValue) pure @safeEncodes a non-negative integer as DER INTEGER content bytes.ubyte[] decodeUnsignedInteger(const(ubyte)[] content) pure @safeDecodes DER INTEGER content bytes to an unsigned big-endian representation.ubyte[] encodeOidFromString(string dotted) pure @safeEncodes an OID from its dotted-decimal string representation to binary.string decodeOidToString(const(ubyte)[] encoded) pure @safeDecodes a binary OID to its dotted-decimal string representation.void appendBase128(ref ubyte[] result, uint value) pure @safeAppends a single OID component value in base-128 encoding.uint decodeBase128(const(ubyte)[] data, ref size_t pos) pure @safeDecodes one base-128-encoded OID component starting at `pos`.