asn
ASN.1 DER parser - tag/length/value decoding, OID strings, X.509 certificate parsing, PEM decoding, RSA public key extraction. Pure ilusm.
Load with: use asn
What this module does
asn parses binary ASN.1 DER data entirely in ilusm - no native bindings needed.
You can feed it raw DER bytes or a PEM string and walk the tree of TLV (tag-length-value) nodes,
decode OIDs to dotted notation, extract X.509 certificate fields (subject, issuer, serial number,
validity dates, public key), and pull RSA modulus and exponent out of a certificate's public key.
DER tags are described by three fields: cls (class: universal/application/context/private),
pc (primitive or constructed), and num (the tag number).
Long-form tags (tag number >= 0x1F) are not supported and will error.
Quick example
use asn
# Parse a PEM certificate
cert = asncr(pem_string)
prn(cert.subj) # "/CN=example.com/O=Acme Ltd"
prn(cert.iss) # "/CN=Let's Encrypt..."
prn(cert.sn) # serial number as integer
prn(cert.notb) # not-before validity string
prn(cert.nota) # not-after validity string
# Extract RSA public key integers
rsa = asnrs(cert)
prn(rsa.n) # modulus
prn(rsa.e) # exponent
Functions
Tag constants
Defined as constants for use when inspecting tag classes and primitive/constructed bits.
asnclsuniversal = 0x00, asnclsapp = 0x40, asnclscxt = 0x80, asnclspriv = 0xC0
The four ASN.1 tag classes as constants.
asnpcpri = 0x00, asnpccon = 0x20
Primitive (0x00) and constructed (0x20) bit constants for the P/C flag in a tag byte.
Low-level parsing
asnta(d, i)
Reads a tag byte from byte string d at position i. Returns {cls, pc, num, pos} - class bits, primitive/constructed bit, tag number, and the position after the tag byte. Errors on out-of-bounds or long-form tags.
asnle(d, i)
Reads the length field from d at position i. Handles both short form (single byte) and long form (length-of-length prefix, up to 4 bytes). Returns {len, pos}. Errors on indefinite-length (n == 0) or lengths needing more than 4 bytes.
asntl(d, i)
Parses one complete TLV (tag-length-value) starting at position i. Returns {tag, val, raw, pos} - val is the value bytes, raw includes the full TLV bytes, pos is where the next TLV starts.
asnpa(d, i)
Recursively parses a DER structure starting at i. For constructed nodes, recursively parses all children into a kids list. For primitive nodes, returns the raw value bytes. Returns {tag, raw, kids?} or {tag, raw, val}.
PEM decoding
asnpe(s)
Strips PEM armour (-----BEGIN ...----- / -----END ...----- lines) from a string, concatenates the base64 body lines, and decodes to raw DER bytes via enc.encub.
Value decoders
asnoi(b)
Decodes OID bytes to a dotted decimal string like "1.2.840.113549.1.1.11". The first byte encodes the first two arcs as first/40 and first%40. Subsequent bytes use base-128 variable-length encoding.
asnin(b)
Decodes a big-endian signed integer from DER bytes. Handles negative values (high bit set on first byte means two's complement). Returns 0 for empty input.
Tree navigation
asnfi(n, path)
Finds a descendant node by walking a path of tag numbers. Each element in path is a tag number to match against children. Returns the found node or errors with the missing tag number.
X.509 certificates
asncr(d)
Parses an X.509 certificate from raw DER bytes. Returns {subj, iss, pub, sn, notb, nota} - subject name, issuer name (both as /CN=.../O=... strings), raw public key bytes, serial number as integer, and the not-before/not-after validity strings.
asncr(s)
Overload that accepts a PEM string. Calls asnpe to strip armour first, then parses the DER.
Distinguished name formatting
asnna(n)
Converts an X.500 RelativeDistinguishedName node to an /attr=value string. Recognises the following OIDs: 2.5.4.6 → C, 2.5.4.8 → ST, 2.5.4.7 → L, 2.5.4.10 → O, 2.5.4.11 → OU, 2.5.4.3 → CN, 2.5.4.5 → SN. Unknown OIDs are used as-is.
RSA public key extraction
asnrs(c)
Extracts the RSA public key from a parsed cert object (c.pub). Parses the SubjectPublicKeyInfo structure, skips the BIT STRING wrapper byte, and returns {n, e} - modulus and public exponent as large integers decoded by asnin.
Notes
- Long-form tags (tag number >= 31 / 0x1F) are not supported -
asntawill error. - Length fields requiring more than 4 bytes are rejected.
asncris overloaded: one signature takes DER bytes, the other takes a PEM string.- The module relies on
encfor byte-level access and base64 decoding.