2.3 KiB
math/crt
Purpose
RSA private-key operation via the Chinese Remainder Theorem (RFC 8017 §5.1.2,
second-form algorithm). Computes m = c^d mod n using the CRT parameters
p, q, dp, dq, qInv already stored on the canonical RsaPrivateKey shape, so
the working modulus during exponentiation is half the size of n.
Empirically the CRT path is 3-4× faster than the naive c^d mod n route on
2048-bit keys; the speed-up grows quadratically with modulus size. Stage 1
ships the algorithm; Stages 2-3 wire it into rsaSign* and rsaDecrypt*
once MGF1 + EMSA encoding modules land.
Features
- Pure-function implementation — no allocation beyond
bigintintermediates. - Reuses
modPowso the banned-pattern grep gate stays clean. - Negative-h fix-up (
h += pwhen negative) is constant-form in TypeScript so the JIT does not branch-predict away the canonicalisation step.
Usage: Basic Example
import { rsaPrivateOperationCrt } from "@suaveplan/crypto-rsa/math";
const m = rsaPrivateOperationCrt(c, privateKey);
Usage: Advanced Example
import {
i2osp,
os2ip,
rsaPrivateOperationCrt,
} from "@suaveplan/crypto-rsa/math";
function decryptCiphertextBytes(
ciphertext: Uint8Array,
key: RsaPrivateKey
): Uint8Array {
const c = os2ip(ciphertext);
const m = rsaPrivateOperationCrt(c, key);
return i2osp(m, ciphertext.length);
}
API Reference
rsaPrivateOperationCrt(c: bigint, key: RsaPrivateKey): bigint
Returns the message representative m ∈ [0, n) such that m^e mod n === c.
Requires c < n (caller's responsibility — the CRT formulation does not
verify the bound).
Implementation Notes
The second-form algorithm (RFC 8017 §5.1.2) is preferred over the first-form
because it never materialises any value larger than p or q during the hot
loop, keeping memory pressure halved. The final reconstruction m = m2 + h*q
returns a value in [0, n) provided c < n; with c >= n the result is
mathematically valid but semantically meaningless because RSA encrypted/signed
representatives are always reduced mod n.
Negative h arises when m1 < m2. The if (h < 0n) h += p step canonicalises
h into [0, p) before the multiplication so the final m2 + h*q is
unambiguously non-negative.