Files
skills/docs/security-stack/crypto/crypto-rsa/src/keygen/multi-prime.md
2026-05-29 08:20:56 +01:00

3.3 KiB

keygen/multi-prime

Purpose

Multi-prime RSA key generation per RFC 8017 §3 and PKCS #1 Appendix A.1.2 OtherPrimeInfos extension. Reachable via the public generateRsaKeyPair({ primes: 3 | 4 | 5 }) entry point; this module is the algorithmic core.

Multi-prime RSA trades a small reduction in security per bit (the modulus must be slightly larger to retain the same factoring hardness) for a substantial speedup of the private operation — each prime factor is smaller, and CRT-accelerated decryption runs primes exponentiations of bitLength / primes-sized operands instead of two exponentiations of bitLength / 2.

Features

  • 3-, 4-, and 5-prime modes (PKCS #1 declares no upper bound but this module caps at 5 because beyond that the security margin per bit becomes uneconomical).
  • Reuses the two-prime samplePrime helper for each factor — same Miller-Rabin gate, same coprimality check, same AbortSignal threading.
  • Outputs a canonical RsaPrivateKey with the largest two primes in the standard (p, q, dp, dq, qInv) slots and the rest in the optional otherPrimeInfos field.
  • Round-trips through PKCS #1 (serializeRsaPrivateKeyPkcs1 / parseRsaPrivateKeyPkcs1) — the serializer emits version 1 with the full OtherPrimeInfos SEQUENCE OF when otherPrimeInfos is present.

Usage: Basic Example

import { generateRsaKeyPair } from "@suaveplan/crypto-rsa/keygen/generate";

const key3 = await generateRsaKeyPair({
    modulusBits: 2048,
    primes: 3,
});
console.log(key3.otherPrimeInfos?.length); // 1

Usage: Advanced Example

Round-trip a 3-prime key through PKCS #1 DER:

import {
    generateRsaKeyPair,
    parseRsaPrivateKeyPkcs1,
    serializeRsaPrivateKeyPkcs1,
} from "@suaveplan/crypto-rsa";

const key = await generateRsaKeyPair({ modulusBits: 1536, primes: 3 });
const der = serializeRsaPrivateKeyPkcs1(key);
const restored = parseRsaPrivateKeyPkcs1(der);
console.log(restored.otherPrimeInfos?.length); // 1

API Reference

generateMultiPrimeKey(options): Promise<RsaPrivateKey>

Internal entry — public callers should use generateRsaKeyPair.

  • options.modulusBits: number
  • options.publicExponent: bigint
  • options.primes: number — must be 3, 4, or 5.
  • options.rng: Rng
  • options.signal: AbortSignal | undefined

Throws CRYPTO_RSA.PRIME_INVALID on bad primes, CRYPTO_RSA.KEYGEN_FAILED on outer-loop exhaustion (32 attempts without producing a coprime modulus).

Implementation Notes

  • The (p, q) selection picks the two largest primes so the standard CRT path operates on the bigger half of the modulus — this matches OpenSSL's multi-prime convention and mirrors what most PKCS #1 consumers expect when reading version 1 keys.
  • The otherPrimeInfos[i].t coefficient is (r_1 * r_2 * ... * r_(i-1))^-1 mod r_i per RFC 8017 §3 — we maintain runningProduct rather than recomputing each step.
  • Outer loop bails after MAX_OUTER_ATTEMPTS = 32 attempts; in practice every well-formed (modulusBits, primes) pair succeeds on the first attempt because the small-prime trial division in isProbablePrime already culls most non-coprime candidates upstream.
  • lcm(a, b) = (a / gcd(a, b)) * b — the reverse (a * b) / gcd formulation overflows V8's bigint scratch for λ(n) with 4096-bit moduli; this rearrangement avoids it.