first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# `signature/verify` — Signature verify dispatch over crypto-rsa and crypto-curve
## Purpose
The `signature/verify` 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.