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,66 @@
# `keys/parse-pkcs1-private`
## Purpose
Parses a DER-encoded `RSAPrivateKey` per RFC 8017 Appendix A.1.2 into the
canonical `RsaPrivateKey` shape with mandatory CRT parameters
(`p`, `q`, `dp`, `dq`, `qInv`). Also exports `finalisePrivateKey` so the
PKCS#8 and JWK parsers share the same field-positivity validation.
Multi-prime RSA (`version == 1` with non-empty `otherPrimeInfos`) is recognised
but explicitly rejected with `CRYPTO_RSA.UNSUPPORTED_FORMAT` — the wider
package contract assumes two-prime RSA throughout.
## Features
- Strict-DER `RSAPrivateKey` parser via `DerReader`.
- Version validation (`0` two-prime, `1` multi-prime — both detected; only
`0` accepted).
- Multi-prime detection via either `version === 1` OR a trailing SEQUENCE
(covers conformant and non-conformant emitters).
- Per-field positivity gate via `finalisePrivateKey`.
- Bit-length derivation from `n.toString(2).length`.
## Usage: Basic Example
```ts
import { parseRsaPrivateKeyPkcs1 } from "@suaveplan/crypto-rsa";
const key = parseRsaPrivateKeyPkcs1(derBytes);
// key.n, key.e, key.d, key.p, key.q, key.dp, key.dq, key.qInv, key.bitLength
```
## Usage: Advanced Example
```ts
import { finalisePrivateKey } from "@suaveplan/crypto-rsa/keys";
const key = finalisePrivateKey({ n, e, d, p, q, dp, dq, qInv });
```
## API Reference
### `parseRsaPrivateKeyPkcs1(bytes: Uint8Array): RsaPrivateKey`
Throws `CryptoRsaError(CRYPTO_RSA.INVALID_KEY)` on structural problems and
on any non-positive field. Throws `CryptoRsaError(CRYPTO_RSA.UNSUPPORTED_FORMAT)`
on multi-prime input.
### `finalisePrivateKey(inputs): RsaPrivateKey`
Validates each of `n, e, d, p, q, dp, dq, qInv` is `> 0n` and computes
`bitLength` from `n`. Surfaces the same `INVALID_KEY` error class as the
DER parser.
## Implementation Notes
The parser uses both `version === 1n` and a trailing-SEQUENCE peek to detect
multi-prime keys. Some emitters set `version` to `0` even when they include
`otherPrimeInfos`; we reject either flag to avoid silently truncating the
prime set.
The fields are read in fixed order with `seq.readInteger()` calls; if any
field is missing the underlying `DerReader` raises `INVALID_KEY` with a
truncation context. The final `seq.assertEnd()` ensures no extra fields
slip through (other than the multi-prime trailing SEQUENCE that we explicitly
detected and rejected).