Files
skills/docs/security-stack/crypto/crypto-rsa/src/keys/parse-pkcs1-private.md
2026-05-29 08:20:56 +01:00

2.3 KiB

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

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

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