Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
# `keys/parse-spki`
## Purpose
Parses an X.509 `SubjectPublicKeyInfo` per RFC 5280 §4.1 + Appendix A and
unwraps the inner PKCS#1 `RSAPublicKey`. SPKI is the canonical wire format
for RSA public keys in TLS certificates (`Certificate.tbsCertificate.subjectPublicKeyInfo`),
JWK headers (`x5c`/`x5t#S256` reference chains), and the WebAuthn TPM
attestation statement.
The parser enforces the `1.2.840.113549.1.1.1` `rsaEncryption` algorithm OID
and the canonical `NULL` algorithm parameters per RFC 3279 §2.3.1.
## Features
- DER outer-SEQUENCE → AlgorithmIdentifier → BIT STRING walk.
- Algorithm OID equality check against `OID_RSA_ENCRYPTION`.
- `NULL` algorithm-parameters enforcement (RFC 3279 §2.3.1).
- Delegates inner PKCS#1 parse to `parseRsaPublicKeyPkcs1`.
## Usage: Basic Example
```ts
import { parseRsaPublicKeySpki } from "@suaveplan/crypto-rsa";
const key = parseRsaPublicKeySpki(spkiDerBytes);
```
## Usage: Advanced Example
```ts
import { parseRsaPublicKeySpki } from "@suaveplan/crypto-rsa";
// SPKI carrying an EC OID rejects with UNSUPPORTED_FORMAT.
try {
parseRsaPublicKeySpki(ecSpkiBytes);
} catch (error) {
if (error instanceof CryptoRsaError && error.code === "CRYPTO_RSA.UNSUPPORTED_FORMAT") {
// dispatch to @suaveplan/crypto-curve
}
}
```
## API Reference
### `parseRsaPublicKeySpki(bytes: Uint8Array): RsaPublicKey`
Throws `CryptoRsaError(CRYPTO_RSA.UNSUPPORTED_FORMAT)` for non-RSA OIDs.
Throws `CryptoRsaError(CRYPTO_RSA.INVALID_KEY)` on structural problems
(missing fields, trailing data, unused-bits ≠ 0 in the `BIT STRING`).
## Implementation Notes
The `BIT STRING` payload is copied (defensive copy in `DerReader.readBitString`)
so the inner PKCS#1 reader never aliases the input buffer. This costs one
allocation per parse but eliminates a class of subtle bugs where downstream
mutation of the inner buffer would corrupt the SPKI input.
`alg.assertEnd()` and `outer.assertEnd()` together guarantee no extra fields
slipped through. RFC 3279 forbids extra parameters in the `rsaEncryption`
algorithm identifier, and RFC 5280 forbids extra fields in `SubjectPublicKeyInfo`.