2.8 KiB
2.8 KiB
asn1/strings — typed-string decoders
Purpose
Decodes and encodes the typed ASN.1 string types used inside X.509 Names and SubjectAltName entries: UTF8String, PrintableString, IA5String, TeletexString, BMPString, UniversalString. The encoder picks the most-restrictive form that holds the input value per RFC 5280 paragraph 7. Decoder is strict about character-set membership — invalid PrintableString characters are rejected as ASN1_MALFORMED.
Features
- UTF-8 decode via
TextDecoderwithfatal: true, so invalid UTF-8 is rejected (not replaced). PrintableStringalphabet check per ITU-T X.520 — letters, digits, space, and the eleven punctuation characters allowed.IA5String0x00-0x7F check.BMPString(UCS-2 big-endian) andUniversalString(UCS-4 big-endian) decode.TeletexStringpragmatically decoded as Latin-1; sufficient for the rare legacy CAs that still emit it.- Encoder picks
PrintableStringwhen valid, falling back toUTF8String— matches RFC 5280 paragraph 7.1 "most-restrictive" rule.
Usage: Basic Example
import { decodeAsn1String, encodeAsn1String, UNIVERSAL_TAGS } from "@suaveplan/x509/asn1";
const s = decodeAsn1String(UNIVERSAL_TAGS.UTF8_STRING, new Uint8Array([0x68, 0x69])); // "hi"
const { tagNumber, body } = encodeAsn1String("Example CA");
// tagNumber === UNIVERSAL_TAGS.PRINTABLE_STRING
Usage: Advanced Example
import { decodeAsn1, decodeAsn1String, UNIVERSAL_TAGS } from "@suaveplan/x509/asn1";
// Decode a Name attribute value where the tag depends on the CA's choice:
const attrNode = decodeAsn1(attrBytes);
if (!("content" in attrNode)) throw new Error("expected primitive");
const cn = decodeAsn1String(attrNode.tag.tagNumber, attrNode.content);
API Reference
decodeAsn1String(tagNumber: number, body: Uint8Array): string— dispatches on the universal tag; throwsX509Error(ASN1_MALFORMED)on unsupported tag or character-set violation.encodeAsn1String(value: string): { tagNumber, body }— returns the most-restrictive choice that holds the value.
Implementation Notes
PrintableStringregex covers ITU-T X.520 paragraph 6.1 — letters, digits, space, and the eleven allowed punctuation marks.TeletexString(T.61) is technically a 7/8-bit ISO 2022 escape system with national variants; decoding as Latin-1 is the de-facto industry practice (BoringSSL, OpenSSL).BMPStringandUniversalStringare byte-order strict — the BMP form is UCS-2 big-endian (2 bytes per char), Universal is UCS-4 big-endian (4 bytes per char).- The encoder does not pick
IA5String,TeletexString,BMPString, orUniversalString— these are accepted when reading legacy certs but every newly-encoded value defaults toUTF8String(the modern X.509 recommendation per RFC 5280 paragraph 4.1.2.4).