2.0 KiB
pem/pem-codec
Purpose
Underlying RFC 7468 textual-encoding codec used by the four PEM parse/serialise entry points in this module. Splits the codec from the public-key-specific dispatchers so the parser logic (label whitelist, mismatched BEGIN/END detection, base64 strict-grammar enforcement) lives in exactly one place.
Features
decodePem(pem, allowedLabels)— line-tolerant scan for matching BEGIN/END armor, label whitelist enforcement, body base64 round-trip.encodePem(label, body)— canonical 64-char body line emission with trailing newline.- All failure modes raise
CryptoRsaError(CRYPTO_RSA.PEM_MALFORMED).
Usage: Basic Example
import { decodePem, encodePem } from "@suaveplan/crypto-rsa/pem";
const decoded = decodePem(pemString, ["PUBLIC KEY"]);
const back = encodePem("PUBLIC KEY", decoded.body);
Usage: Advanced Example
import { decodePem } from "@suaveplan/crypto-rsa/pem";
const { label, body } = decodePem(input, ["PUBLIC KEY", "RSA PUBLIC KEY"]);
// Dispatch on label to the appropriate DER parser.
API Reference
decodePem(pem: string, allowedLabels: readonly string[]): DecodedPem
Returns { label, body }. Throws PEM_MALFORMED on missing BEGIN line,
unknown label, missing matching END line, empty body, non-base64 body
characters, or base64-decode failure.
encodePem(label: string, body: Uint8Array): string
Returns the canonical PEM block.
interface DecodedPem { readonly label: string; readonly body: Uint8Array }
Implementation Notes
The body grammar is enforced before base64 decoding because some base64
implementations silently accept non-canonical characters (whitespace, _,
-) that violate strict RFC 7468. We require the strict alphabet
[A-Za-z0-9+/=] to ensure round-trip determinism.
The codec accepts both LF and CRLF line endings on parse but always emits LF — the canonical form recommended by RFC 7468 §2 for systems with flexible line-ending support. CRLF emission is left to the consumer (e.g. HTTP frameworks) as a transport-layer concern.