Initial Commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# `extensions/key-usage` — Key Usage flags bit-string
|
||||
|
||||
## Purpose
|
||||
|
||||
Decodes the `key-usage` extension per RFC 5280 paragraph 4.2. Every public field in the resulting type is captured from the DER value; OCTET STRING wrappers are stripped at the extension boundary so this module operates directly on the inner ASN.1 value. The decoded shape feeds `validateChain` (for critical-extension enforcement, key-usage gating on issuers, name-constraint matching, and trust-anchor SKI lookup) and is also exposed as the structured form sibling packages such as `@suaveplan/x509-crl` and `@suaveplan/webauthn` consume.
|
||||
|
||||
## Features
|
||||
|
||||
- Strict DER decode at the extension boundary.
|
||||
- Discriminated-union return where the underlying ASN.1 CHOICE permits multiple shapes.
|
||||
- Helpful `X509Error(EXTENSION_MALFORMED)` on every shape violation, with the failing reason captured in `error.context.reason` so callers can diagnose specific malformations.
|
||||
- Zero allocations beyond the typed result; raw extension bytes are subarrayed, not copied through intermediate buffers.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { decodekey_usage } from "@suaveplan/x509/extensions";
|
||||
import { parseCertificate } from "@suaveplan/x509/certificate";
|
||||
|
||||
const cert = parseCertificate(derBytes);
|
||||
const ext = cert.tbs.extensions.find((e) => e.oid === "<oid>");
|
||||
if (ext !== undefined) {
|
||||
const decoded = decodekey_usage(ext.value);
|
||||
// ... consume decoded ...
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { decodeExtension } from "@suaveplan/x509/extensions";
|
||||
import { parseCertificate } from "@suaveplan/x509/certificate";
|
||||
|
||||
// Route every extension through the dispatch registry — the result is a
|
||||
// discriminated union over every supported kind plus a "raw" fallback.
|
||||
const cert = parseCertificate(derBytes);
|
||||
for (const raw of cert.tbs.extensions) {
|
||||
const decoded = decodeExtension(raw);
|
||||
if (decoded.kind === "raw" && decoded.critical) {
|
||||
throw new Error("unknown critical extension: " + decoded.oid);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- Concrete decoder `decodekey_usage(value: Uint8Array)` exported from this module.
|
||||
- OID string constant exported alongside the decoder.
|
||||
- `decodeExtension(raw)` in `./registry.ts` dispatches by OID through this module.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The decoder operates on the OCTET STRING value of the extension as carried by `RawExtension.value` — callers pass exactly those bytes.
|
||||
- Critical-extension semantics are NOT enforced at this layer; `validateChain` handles the §6.1.4(f) refusal on unknown critical extensions by inspecting `RawExtension.critical` directly.
|
||||
- ASN.1 shape violations surface as `X509Error(EXTENSION_MALFORMED)` with the failing reason captured for diagnostics.
|
||||
- The module emits no OpenTelemetry — that surface lives in `certificate/parse` (which records the per-extension counter) and `validate/validate-chain` (which records the per-validation histogram).
|
||||
Reference in New Issue
Block a user