← Week 4: X.509 Certificates

Day 22: ASN.1 and DER Encoding

Phase 1 · June 4, 2026

← Week 4: X.509 Certificates

Agenda (2–3 hours)

  • Read (60 min): "A Layman's Guide to a Subset of ASN.1, BER, and DER" — Burton Kaliski (RSA Labs, 1993, free PDF, ~25 pages — read in full)
  • Study (45 min): TLV structure, DER rules, OIDs
  • Practice (45 min): Decode a certificate with openssl asn1parse; manual TLV parsing
  • Challenge (30 min): Manually parse first bytes of a DER-encoded cert
← Week 4: X.509 Certificates

Why ASN.1 and DER Matter

X.509 certificates are encoded in DER (Distinguished Encoding Rules),
a strict subset of BER (Basic Encoding Rules), defined by ASN.1 schemas.

If you don't understand DER, certificate binary formats are opaque.
If you do understand DER, you can:

  • Read raw cert bytes
  • Understand parsing libraries
  • Debug encoding mismatches (very common in HSM/CA integrations)
  • Spot malformed certs before they cause runtime failures
← Week 4: X.509 Certificates

TLV: Tag, Length, Value

Every ASN.1 element is encoded as:

[Tag: 1+ bytes] [Length: 1+ bytes] [Value: length bytes]

Tag byte (first byte):

bits 7-6: class (00=universal, 01=application, 10=context, 11=private)
bit 5:    constructed (1) vs primitive (0)
bits 4-0: tag number

Common universal tags:

Tag Type
0x02 INTEGER
0x03 BIT STRING
0x04 OCTET STRING
0x05 NULL
0x06 OID
0x0C UTF8String
0x13 PrintableString
0x17 UTCTime
0x30 SEQUENCE (constructed)
0x31 SET (constructed)
← Week 4: X.509 Certificates

Length Encoding

Short form (value < 128): 1 byte, MSB = 0
  e.g., 0x05 = length 5

Long form (value >= 128): first byte has MSB=1, low 7 bits = # of following bytes
  e.g., 0x82 0x01 0x2F = length 303
       (0x82 → 2 following length bytes, 0x012F = 303)

Indefinite form: BER only, not allowed in DER
← Week 4: X.509 Certificates

Object Identifiers (OIDs)

OIDs encode a dotted-decimal path (e.g., 2.5.4.3 for commonName).

Encoding rules:

  • First two components encoded as 40 * first + second in one byte
  • Remaining components encoded in base-128 with continuation bits
2.5.4.3:
  2*40 + 5 = 85 = 0x55
  4 = 0x04
  3 = 0x03
  DER: 06 03 55 04 03

You don't need to implement this — just understand it enough to read dumps.

← Week 4: X.509 Certificates

Practice Exercise

# Decode a real certificate
openssl x509 -in /etc/ssl/certs/ca-certificates.crt -noout -text | head -5
# or grab one from a server
openssl s_client -connect amazon.com:443 2>/dev/null | \
  openssl x509 -noout -text > /tmp/amazon.txt && head -30 /tmp/amazon.txt

# Raw ASN.1 parse
openssl s_client -connect amazon.com:443 2>/dev/null | \
  openssl x509 | openssl asn1parse | head -30
← Week 4: X.509 Certificates

Challenge Assignment

Take a PEM certificate, base64-decode the body to get raw DER bytes.
Manually parse the first 10 bytes by hand:

  1. What is the outer tag? (Should be 0x30 — SEQUENCE)
  2. How many bytes is the length field?
  3. What is the total length of the certificate content?
  4. What is the tag of the first inner element? (Should be another 0x30 — TBSCertificate)
  5. Verify your manual parse against openssl asn1parse -inform DER

Write a Rust function parse_tlv(bytes: &[u8]) -> (u8, usize, &[u8]) that returns
(tag, content_length, content_bytes) for the first TLV in a byte slice.

← Week 4: X.509 Certificates

Resources

  • Kaliski, "A Layman's Guide to ASN.1, BER, and DER" (search for the RSA Labs PDF)
  • RFC 5280 Appendix A: ASN.1 module for X.509
  • openssl asn1parse man page