@lanitlabs/pqc-lnqc714
v1.1.1
Published
Post-Quantum KEM — LPN-based key encapsulation with LDPC error correction. Constant-time Rust/WASM engine.
Readme
@lanitlabs/pqc-lnqc714
Post-Quantum Key Encapsulation Mechanism (KEM) — LPN-based key agreement with LDPC error correction.
Constant-time Rust/WASM engine targeting browsers, Node.js, and Edge runtimes.
npm install @lanitlabs/pqc-lnqc714Overview
LNQC-714 is a KEM whose security reduces to the hardness of the fixed-weight Learning Parity with Noise (LPN) problem over GF(2). A Low-Density Parity-Check (LDPC) code with a Gallager bit-flipping decoder absorbs the sparse LPN noise, achieving 0% decryption failure at the security parameters:
| Parameter | Value |
|---|---|
| LPN dimension | n = 512 |
| LPN samples | m = 512 |
| Noise weight | w = 4 |
| LDPC codeword | 2048 bits |
| LDPC data | 256 bits |
| Decoder | Gallager bit-flipping (50 iters) |
| Public key | 262 656 bytes |
| Ciphertext | 1 050 624 bytes |
All operations execute in constant-time binary matrix algebra modulo 2 — no data-dependent branching, no rejection sampling, no modular arithmetic. This provides architectural immunity to cache-timing and power-analysis side-channel attacks.
API
import LNQC from '@lanitlabs/pqc-lnqc714';
// ── Key Generation ──────────────────────────────────────────
const keys = LNQC.keyGen();
// keys.publicKeyA: Uint8Array (512 × 512 bits, row-major)
// keys.publicKeyT: Uint8Array (512 bits)
// keys.privateKey: Uint8Array (512 bits)
// ── Encapsulation ───────────────────────────────────────────
const msg = LNQC.randomBits(256); // 256-bit shared secret
const ct = LNQC.encapsulate(
keys.publicKeyA,
keys.publicKeyT,
msg,
);
// ct.u: Uint8Array (2048 × 512 bits)
// ct.v: Uint8Array (2048 bits)
// ct.byteLength: number
// ── Decapsulation ───────────────────────────────────────────
const recovered = LNQC.decapsulate(
keys.privateKey,
ct.u,
ct.v,
);
// recovered equals `msg` (LDPC decoder corrects LPN noise)
// ── Constant-Time Verification ──────────────────────────────
const match = LNQC.constantTimeVerify(secretA, secretB);
// Returns true/false in constant time (subtle::ConstantTimeEq)Parameter getters
LNQC.getNCols() // 512
LNQC.getMRows() // 512
LNQC.getNoiseWeight() // 4
LNQC.getLdpcDataBits() // 256
LNQC.getLdpcCodewordBits() // 2048Architecture
┌──────────────────────────────────────────────────────────┐
│ JS/TS (consumer) │
│ import LNQC from '@lanitlabs/pqc-lnqc714' │
└─────────────────────┬────────────────────────────────────┘
│
┌─────────────────────▼────────────────────────────────────┐
│ dist/index.js (dynamic loader) │
│ Node.js → pkg/node/pqc_lnqc714.js │
│ Browser → pkg/browser/pqc_lnqc714.js │
└─────────────────────┬────────────────────────────────────┘
│ wasm-bindgen
┌─────────────────────▼────────────────────────────────────┐
│ Rust/WASM (src/crypto.rs) │
│ • Secure RNG via getrandom (os.urandom) │
│ • Regular LDPC construction (col_weight=15) │
│ • Gallager bit-flipping decoder │
│ • Sparse R_indices optimization │
│ • subtle::ConstantTimeEq for verification │
└──────────────────────────────────────────────────────────┘Security
- LPN hardness: No known sub-exponential quantum algorithm.
- CSPRNG: All keys, noise vectors, and ephemeral randomness use
getrandom(OS entropy /crypto.getRandomValues). No insecure PRNG (PCG, xorshift) is used for security-critical data. - Constant-time: The
subtlecrate guards token comparison against timing side-channels. - LDPC protection: Regular column-weight-15 parity-check matrix eliminates single-check failure modes.
License
MIT
