Files
skills/docs/security-stack/security/x509/src/extensions/basic-constraints.md
2026-05-29 08:20:56 +01:00

2.3 KiB

extensions/basic-constraints — RFC 5280 paragraph 4.2.1.9

Purpose

Decodes the basic-constraints extension into BasicConstraints { cA: boolean; pathLenConstraint?: number }. During path validation, every non-leaf certificate in the chain SHALL have cA: true; the pathLenConstraint field bounds the number of non-self-issued intermediates beneath the issuer per RFC 5280 paragraph 6.1.4(h).

Features

  • Strict DER decode of the SEQUENCE wrapper.
  • Default cA: false when the BOOLEAN field is absent (matches RFC 5280 paragraph 4.2.1.9 default).
  • INTEGER decode for pathLenConstraint with bounded length (up to 4 bytes) and non-negative check.
  • Rejects extra fields beyond (cA, pathLenConstraint) as X509Error(EXTENSION_MALFORMED).

Usage: Basic Example

import { decodeBasicConstraints } from "@suaveplan/x509/extensions";

const bc = decodeBasicConstraints(extensionValueBytes);
if (bc.cA && bc.pathLenConstraint !== undefined) {
    console.log("CA with max", bc.pathLenConstraint, "non-self-issued intermediates");
}

Usage: Advanced Example

import { decodeBasicConstraints } from "@suaveplan/x509/extensions";
import { parseCertificate } from "@suaveplan/x509/certificate";

const cert = parseCertificate(derBytes);
const ext = cert.tbs.extensions.find((e) => e.oid === "2.5.29.19");
if (ext !== undefined) {
    const bc = decodeBasicConstraints(ext.value);
    if (!bc.cA) {
        throw new Error("issuer must have cA: true");
    }
}

API Reference

  • decodeBasicConstraints(value: Uint8Array): BasicConstraints — decode an extension value (the OCTET STRING contents). Throws X509Error(EXTENSION_MALFORMED) on shape violation.
  • OID_BASIC_CONSTRAINTS — string constant "2.5.29.19".

Implementation Notes

  • cA defaults to false when the BOOLEAN field is absent; this is what RFC 5280 paragraph 4.2.1.9 mandates.
  • The bound on pathLenConstraint length (4 bytes) is overgenerous — real-world values fit in a single byte — but matches the canonical DER encoding of small INTEGERs and rejects deliberately oversized values as malformed.
  • The bound n < 0 is also redundant since the bit-shift always produces non-negative values for content lengths up to 4 bytes; the check exists as defensive depth and is exercised by malformed-input tests.