Skip to content

micro509/der

DER reading and writing primitives.

The building blocks every other entrypoint is made of, for the cases the typed APIs do not cover:

Reading accepts definite lengths and minimal length encodings, rejects the high-tag-number form, and applies a nesting-depth guard capped at DEFAULT_MAX_DER_DEPTH. BER-only constructs fail.

Readers and decoders take untrusted bytes, so each one comes as a pair:

Writers take typed input and throw, matching encodeName and pemEncode.

All operations are synchronous.

DecodeDerErrorCode

Machine-readable failure reason for the DER readers and decoders.

ts
type DecodeDerErrorCode = malformed

DecodeDerFailure

Structured failure payload for DER reading and decoding.

ts
interface DecodeDerFailure extends Micro509Error<DecodeDerErrorCode> {
	readonly ok: false;
}

Properties

  • readonly ok: false — Always false for failures.

DecodeDerResult

Success-or-failure result from a DER reader or decoder.

ts
type DecodeDerResult<TValue> = {
  readonly ok: true;
  readonly value: TValue
} | ErrorResult<DecodeDerErrorCode, Record<never, never>, DecodeDerFailure>

decodeDerBitString

Decodes a BIT STRING element (tag 0x03) into a DerBitString.

Unused trailing bits are returned as encoded, with a violation of X.690 §11.2.1 reported through DerBitString.nonZeroPadding, since certificates in the wild carry them.

ts
function decodeDerBitString(
	element: DerElement,
): DecodeDerResult<DerBitString>

Parameters

decodeDerBitStringOrThrow

Decodes a BIT STRING element (tag 0x03) into a DerBitString.

Unused trailing bits are returned as encoded, with a violation of X.690 §11.2.1 reported through DerBitString.nonZeroPadding, since certificates in the wild carry them.

ts
function decodeDerBitStringOrThrow(
	element: DerElement,
): DerBitString

Parameters

Throws

  • if element is mis-tagged, or claims more than seven unused bits.

decodeDerBoolean

Decodes a BOOLEAN element (tag 0x01).

ts
function decodeDerBoolean(
	element: DerElement,
): DecodeDerResult<boolean>

Parameters

decodeDerBooleanOrThrow

Decodes a BOOLEAN element (tag 0x01).

ts
function decodeDerBooleanOrThrow(
	element: DerElement,
): boolean

Parameters

Throws

  • if element is mis-tagged, or holds anything but 0x00 or 0xff.

decodeDerInteger

Decodes an INTEGER element (tag 0x02) into a number.

ts
function decodeDerInteger(
	element: DerElement,
): DecodeDerResult<number>

Parameters

decodeDerIntegerOrThrow

Decodes an INTEGER element (tag 0x02) into a number.

ts
function decodeDerIntegerOrThrow(
	element: DerElement,
): number

Parameters

Throws

  • if element is mis-tagged, negative, non-minimally encoded, or exceeds Number.MAX_SAFE_INTEGER.

decodeDerOctetString

Decodes an OCTET STRING element (tag 0x04) into its payload bytes.

ts
function decodeDerOctetString(
	element: DerElement,
): DecodeDerResult<Uint8Array>

Parameters

decodeDerOctetStringOrThrow

Decodes an OCTET STRING element (tag 0x04) into its payload bytes.

ts
function decodeDerOctetStringOrThrow(
	element: DerElement,
): Uint8Array

Parameters

Throws

decodeDerOid

Decodes an OBJECT IDENTIFIER element (tag 0x06) into dotted-decimal form.

ts
function decodeDerOid(
	element: DerElement,
): DecodeDerResult<string>

Parameters

decodeDerOidOrThrow

Decodes an OBJECT IDENTIFIER element (tag 0x06) into dotted-decimal form.

ts
function decodeDerOidOrThrow(
	element: DerElement,
): string

Parameters

Throws

  • if element is mis-tagged, or holds a malformed sub-identifier.

decodeDerString

Decodes a string element into text, dispatching on its tag.

Supports UTF8String, PrintableString, IA5String, UniversalString, and BMPString.

ts
function decodeDerString(
	element: DerElement,
): DecodeDerResult<string>

Parameters

decodeDerStringOrThrow

Decodes a string element into text, dispatching on its tag.

Supports UTF8String, PrintableString, IA5String, UniversalString, and BMPString.

ts
function decodeDerStringOrThrow(
	element: DerElement,
): string

Parameters

Throws

  • on TeletexString, and on every other string tag.

decodeDerTime

Decodes a UTCTime (tag 0x17) or GeneralizedTime (tag 0x18) element into a Date.

ts
function decodeDerTime(
	element: DerElement,
): DecodeDerResult<Date>

Parameters

decodeDerTimeOrThrow

Decodes a UTCTime (tag 0x17) or GeneralizedTime (tag 0x18) element into a Date.

ts
function decodeDerTimeOrThrow(
	element: DerElement,
): Date

Parameters

Throws

  • if element carries any other tag, or a malformed time value.

derChildren

Reads the direct children of a constructed parent within source.

ts
function derChildren(
	source: Uint8Array,
	parent: DerElement,
): DecodeDerResult<DerElement[]>

Parameters

derChildrenOrThrow

Reads the direct children of a constructed parent within source.

ts
function derChildrenOrThrow(
	source: Uint8Array,
	parent: DerElement,
): DerElement[]

Parameters

Throws

  • if a child overflows parent, or data is left between the last child and its end.

readDerElement

Reads one TLV element from bytes starting at offset.

ts
function readDerElement(
	bytes: Uint8Array,
	offset: number,
): DecodeDerResult<DerElement>

Parameters

  • bytes: Uint8Array
  • offset: number — Byte position of the tag octet. Defaults to 0.

readDerElementOrThrow

Reads one TLV element from bytes starting at offset.

ts
function readDerElementOrThrow(
	bytes: Uint8Array,
	offset: number,
): DerElement

Parameters

  • bytes: Uint8Array
  • offset: number — Byte position of the tag octet. Defaults to 0.

Throws

  • if the element is truncated, indefinite-length, or non-minimally encoded.

readDerRoot

Reads the single top-level TLV element from bytes.

ts
function readDerRoot(
	bytes: Uint8Array,
	options?: ReadRootElementOptions,
): DecodeDerResult<DerElement>

Parameters

readDerRootOrThrow

Reads the single top-level TLV element from bytes.

ts
function readDerRootOrThrow(
	bytes: Uint8Array,
	options?: ReadRootElementOptions,
): DerElement

Parameters

Throws

  • if bytes carries trailing data, or nesting exceeds the depth guard.

readDerSequence

Reads a DER-encoded SEQUENCE from bytes and returns its direct children.

ts
function readDerSequence(
	bytes: Uint8Array,
	options?: ReadSequenceChildrenOptions,
): DecodeDerResult<DerElement[]>

Parameters

readDerSequenceOrThrow

Reads a DER-encoded SEQUENCE from bytes and returns its direct children.

ts
function readDerSequenceOrThrow(
	bytes: Uint8Array,
	options?: ReadSequenceChildrenOptions,
): DerElement[]

Parameters

Throws

  • if the root element is not a SEQUENCE, or if child boundaries are inconsistent.

DerBitString

A BIT STRING payload and the number of unused trailing bits in its final byte.

ts
interface DerBitString {
	readonly bytes: Uint8Array;
	readonly unusedBits: number;
	readonly nonZeroPadding: boolean;
}

Properties

  • readonly bytes: Uint8Array — Payload bytes, excluding the leading unused-bit count octet.
  • readonly unusedBits: number — Unused trailing bits in the final byte, 0 through 7.
  • readonly nonZeroPadding: booleantrue when the original encoding had non-zero padding bits (DER violation).

hexToBytes

Converts a hex string (even or odd length) to a Uint8Array. Odd-length strings are left-padded with a zero nibble.

ts
function hexToBytes(
	value: string,
): Uint8Array

Parameters

  • value: string

toHex

Converts raw bytes to a lowercase hex string with no separator.

ts
function toHex(
	bytes: Uint8Array,
): string

Parameters

  • bytes: Uint8Array

DerElement

A single parsed ASN.1 TLV element with byte-range metadata.

ts
interface DerElement {
	readonly tag: number;
	readonly headerLength: number;
	readonly length: number;
	readonly start: number;
	readonly end: number;
	readonly value: Uint8Array;
}

Properties

  • readonly tag: number — ASN.1 tag byte (e.g. 0x30 for SEQUENCE, 0x02 for INTEGER).
  • readonly headerLength: number — Number of bytes occupied by the tag + length octets.
  • readonly length: number — Byte length of the value portion (excluding tag and length octets).
  • readonly start: number — Byte offset where the value portion begins in the source buffer.
  • readonly end: number — Byte offset one past the last value byte. Equals the next element's header offset.
  • readonly value: Uint8Array — The raw value bytes (slice of the source buffer).

ReadRootElementOptions

Options for readRootElement.

ts
interface ReadRootElementOptions {
	readonly maxDepth?: number;
	readonly allowOpaqueConstructedTags?: readonly number[];
}

Properties

  • readonly maxDepth?: number — Maximum nesting depth for the DER depth check. @default DEFAULT_MAX_DER_DEPTH.
  • readonly allowOpaqueConstructedTags?: readonly number``[] — Constructed tags whose inner bytes may not parse as valid TLV children (e.g. opaque extension values).

ReadSequenceChildrenOptions

Options for readSequenceChildren.

ts
interface ReadSequenceChildrenOptions {
	readonly maxDepth?: number;
	readonly allowOpaqueConstructedTags?: readonly number[];
}

Properties

  • readonly maxDepth?: number — Maximum nesting depth for the DER depth check. @default DEFAULT_MAX_DER_DEPTH.
  • readonly allowOpaqueConstructedTags?: readonly number``[] — Constructed tags whose inner bytes may not parse as valid TLV children (e.g. opaque extension values).

assertDerMaxDepth

Walks the full DER tree rooted in bytes.

Constructed tags with content that cannot be parsed as valid children are tolerated when listed in allowOpaqueConstructedTags.

ts
function assertDerMaxDepth(
	bytes: Uint8Array,
	maxDepth: number,
	options?: {
  readonly allowOpaqueConstructedTags?: readonly number[]
},
): void

Parameters

  • bytes: Uint8Array
  • maxDepth: number
  • options?: { readonly allowOpaqueConstructedTags?: readonly number``[] }

Throws

derBitString

Encodes a DER BIT STRING (tag 0x03).

The value is prefixed with a single octet indicating how many trailing bits in the last byte are unused.

ts
function derBitString(
	value: Uint8Array,
	unusedBits: number,
): Uint8Array

Parameters

  • value: Uint8Array
  • unusedBits: number — Number of unused trailing bits (0–7). Defaults to 0.

derBmpString

Encodes a DER BMPString (tag 0x1e) as big-endian UTF-16.

ts
function derBmpString(
	value: string,
): Uint8Array

Parameters

  • value: string

Throws

  • on lone surrogates and on code points above the Basic Multilingual Plane.

derBoolean

Encodes a DER BOOLEAN (tag 0x01): true0xff, false0x00.

ts
function derBoolean(
	value: boolean,
): Uint8Array

Parameters

  • value: boolean

concatBytes

Concatenates multiple byte arrays into a single Uint8Array.

ts
function concatBytes(
	parts: readonly Uint8Array[],
): Uint8Array

Parameters

  • parts: readonly Uint8Array``[]

DEFAULT_MAX_DER_DEPTH

Maximum nesting depth allowed when recursively walking a DER structure.

Guards against stack exhaustion from pathologically nested input.

ts
const DEFAULT_MAX_DER_DEPTH: 64

derExplicitContext

Wraps a value in an explicit context-specific constructed tag (0xa0 + tag).

Used for optional SEQUENCE fields tagged with [tag] EXPLICIT.

ts
function derExplicitContext(
	tag: number,
	value: Uint8Array,
): Uint8Array

Parameters

  • tag: number
  • value: Uint8Array

derGeneralizedTime

Encodes a Date as a DER GeneralizedTime (tag 0x18), format YYYYMMDDHHMMSSZ.

Uses a four-digit year; required for dates outside the 1950–2049 range.

ts
function derGeneralizedTime(
	date: Date,
): Uint8Array

Parameters

  • date: Date

derIa5String

Encodes a DER IA5String (tag 0x16).

ts
function derIa5String(
	value: string,
): Uint8Array

Parameters

  • value: string

Throws

  • if the input contains any non-ASCII character (code point > 0x7f).

derImplicitConstructedContext

Wraps a value in an implicit context-specific constructed tag (0xa0 + tag).

Used for [tag] IMPLICIT fields whose underlying type is constructed (e.g. SEQUENCE).

ts
function derImplicitConstructedContext(
	tag: number,
	value: Uint8Array,
): Uint8Array

Parameters

  • tag: number
  • value: Uint8Array

derImplicitPrimitiveContext

Wraps a value in an implicit context-specific primitive tag (0x80 + tag).

Used for [tag] IMPLICIT fields whose underlying type is primitive (e.g. OCTET STRING).

ts
function derImplicitPrimitiveContext(
	tag: number,
	value: Uint8Array,
): Uint8Array

Parameters

  • tag: number
  • value: Uint8Array

derInteger

Encodes raw big-endian bytes as a DER INTEGER (tag 0x02).

Strips leading zero bytes for minimal encoding and prepends a zero byte when the high bit is set to keep the value non-negative.

ts
function derInteger(
	bytes: Uint8Array,
): Uint8Array

Parameters

  • bytes: Uint8Array

derIntegerFromNumber

Encodes a non-negative JavaScript number as a DER INTEGER.

ts
function derIntegerFromNumber(
	value: number,
): Uint8Array

Parameters

  • value: number

Throws

  • if the value is not a non-negative safe integer.

derNull

Produces a DER NULL element (tag 0x05, zero-length value).

ts
function derNull(): Uint8Array

derOid

Encodes a dotted-decimal OID string as a DER OBJECT IDENTIFIER (tag 0x06).

Validates arc constraints per X.660: first arc must be 0–2, second < 40 for arcs 0 and 1.
Sub-identifiers are encoded with base-128 continuation.

ts
function derOid(
	oid: string,
): Uint8Array

Parameters

  • oid: string

derOctetString

Wraps raw bytes in an OCTET STRING element (tag 0x04).

ts
function derOctetString(
	value: Uint8Array,
): Uint8Array

Parameters

  • value: Uint8Array

derPrintableString

Encodes a DER PrintableString (tag 0x13).

ts
function derPrintableString(
	value: string,
): Uint8Array

Parameters

  • value: string

Throws

  • if the input contains characters outside the X.520 PrintableString set.

derSequence

Wraps concatenated children in a SEQUENCE (tag 0x30).

ts
function derSequence(
	parts: readonly Uint8Array[],
): Uint8Array

Parameters

  • parts: readonly Uint8Array``[]

derSet

Wraps children in a SET (tag 0x31) after DER-sorting them lexicographically by encoded bytes, as required by X.690 DER.

ts
function derSet(
	parts: readonly Uint8Array[],
): Uint8Array

Parameters

  • parts: readonly Uint8Array``[]

derTime

Encodes a Date as the appropriate DER time type per RFC 5280.

  • utcTime for 1950–2049
  • generalizedTime otherwise
ts
function derTime(
	date: Date,
): Uint8Array

Parameters

  • date: Date

derTlv

Builds a complete DER TLV (tag-length-value) element:

  • one tag octet,
  • the DER-encoded length, then
  • the raw value bytes.
ts
function derTlv(
	tag: number,
	value: Uint8Array,
): Uint8Array

Parameters

  • tag: number
  • value: Uint8Array

derUniversalString

Encodes a DER UniversalString (tag 0x1c) as big-endian UTF-32.

ts
function derUniversalString(
	value: string,
): Uint8Array

Parameters

  • value: string

Throws

  • on lone surrogates.

derUtcTime

Encodes a Date as a DER UTCTime (tag 0x17), format YYMMDDHHMMSSZ.

Only the two-digit year is stored; suitable for dates in 1950–2049.

ts
function derUtcTime(
	date: Date,
): Uint8Array

Parameters

  • date: Date

derUtf8String

Encodes a DER UTF8String (tag 0x0c).

ts
function derUtf8String(
	value: string,
): Uint8Array

Parameters

  • value: string

Released under the MIT License.