Files
2026-05-27 23:47:53 +01:00

3.2 KiB

signature/alg-map — Signature-algorithm OID lookup table

Purpose

The signature/alg-map module is part of the certificate signature-verify pipeline. Together with the rest of the signature/ directory it converts an X.509 signatureAlgorithm OID into a concrete verifier dispatch and runs that verifier against the TBSCertificate bytes the certificate parser captured. RSA-SHA{256,384,512} and RSA-PSS verifies are delegated to @suaveplan/crypto-rsa (the just-shipped sibling package); ECDSA-P{256,384,521} and Ed25519 verifies are delegated to @suaveplan/crypto-curve's p256, p384, p521, and ed25519 namespaces.

Features

  • Pure OID-keyed table — no string parsing, no fallbacks, no implicit defaults.
  • Strict OID lookup; unknown OIDs throw X509Error(SIGNATURE_ALG_UNSUPPORTED) with the offending OID in error.context.
  • Async verify boundary so future engines (e.g. WebCrypto via crypto-browser) can plug in without API changes.
  • Failed verify is converted to X509Error(SIGNATURE_INVALID) so consumers branch on the typed code rather than a boolean return.
  • ECDSA signature is decoded once at the verify boundary; the compact r || s form is then handed to the curve primitive.

Usage: Basic Example

import { resolveSignatureAlgorithm, verifyCertificateSignature } from "@suaveplan/x509/signature";
import { parseCertificate } from "@suaveplan/x509/certificate";

const child = parseCertificate(childBytes);
const parent = parseCertificate(parentBytes);
const ok = await verifyCertificateSignature(
    child.tbsCertificateBytes,
    child.signatureAlgorithm.oid,
    child.signatureValue,
    parent.tbs.subjectPublicKeyInfo
);

Usage: Advanced Example

import {
    resolveSignatureAlgorithm,
    decodeEcdsaSignature,
} from "@suaveplan/x509/signature";

const alg = resolveSignatureAlgorithm("1.2.840.10045.4.3.2");
if (alg.family === "ecdsa") {
    const compact = decodeEcdsaSignature(rawSignatureValue, 32);
    // pass compact into the curve-specific verifier of your choice
}

API Reference

  • resolveSignatureAlgorithm(oid: string): SignatureAlgorithm — typed lookup.
  • verifyCertificateSignature(tbsBytes, sigAlgOid, signature, parentSpki): Promise<boolean>.
  • decodeEcdsaSignature(bytes, fieldLen): Uint8Array — DER SEQUENCE-of-INTEGERs to compact r || s.

Implementation Notes

  • The verify dispatcher catches non-X509Error throws from the underlying crypto engines and wraps them as SIGNATURE_INVALID with the original error as cause — this prevents bigint range errors or noble's internal exceptions from leaking to consumers.
  • ECDSA INTEGER decoding strips a single leading 0x00 when followed by a byte with its high bit set (the canonical positive-INTEGER prefix per X.690 paragraph 8.3.2).
  • RSA SPKI parsing is delegated to @suaveplan/crypto-rsa's parseRsaPublicKey({format: "spki"}) — re-implementing RSA-SPKI parse inline would duplicate code already at 100% coverage in that package.
  • Ed448 is recognised by the OID map but the curve primitive is not yet available in @suaveplan/crypto-curve; verifying an Ed448-signed certificate throws SIGNATURE_ALG_UNSUPPORTED with the OID. This is honest behaviour — silently returning false would mask the missing primitive.