# `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).