first commit
This commit is contained in:
57
docs/security-stack/security/x509/src/signature/alg-map.md
Normal file
57
docs/security-stack/security/x509/src/signature/alg-map.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# `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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user