@pq-jwt/core - npm
npm
Search<br>Sign UpSign In
@pq-jwt/core
1.0.6 • Public • Published 18 hours ago<br>Readme<br>Code Beta<br>2 Dependencies<br>0 Dependents<br>7 Versions<br>PQ-JWT - Universal Post-Quantum JWT Library
A comprehensive, production-ready JavaScript/Node.js library for generating, managing, signing, and verifying Post-Quantum Cryptography (PQC) JSON Web Tokens (JWTs) . It acts as a drop-in successor to broken RS256/ES256 libraries.
This library provides quantum-resistant JWT authentication using pure Javascript implementations of NIST-standardized algorithms via the highly audited @noble/post-quantum package.
Ecosystem
Package<br>Description
@pq-jwt/core<br>This library — sign, verify, ML-DSA, SLH-DSA
PQ-JWT-Demo<br>Full demo — Express, MongoDB, TypeScript, UI
Author
Sachin Ruhil · github.com/ruhil6789
npm: npmjs.com/~ruhil6789
Features
Zero Native Dependencies : Uses pure JS math, running seamlessly in Node.js >= 20.19 without complex C++ bindings.
Post-Quantum Ready : Implements NIST-standardized ML-DSA (Dilithium) and SLH‑DSA (SPHINCS+) signature algorithms.
Familiar API : Syntax identical to classic JWT libraries (sign(), verify(), decode(), refresh()).
Standard JWT Claims : Automatic validation of exp (with duration strings like '1h'), nbf, iss, sub, and aud.
Comprehensive Error Handling : Typed exceptions (TokenExpiredError, SignatureError, InvalidTokenError).
Key Serialization : Export and import keys effortlessly via fast hex encoding.
TypeScript Support : Full .d.ts types included out of the box.
Requirements
Node.js 20.19.0 or higher
Installation
npm
npm install @pq-jwt/core
yarn
yarn add @pq-jwt/core
pnpm
pnpm add @pq-jwt/core
Quick Start
Basic Sign & Verify
import { generateKeyPair, sign, verify } from "@pq-jwt/core";
// 1. Generate keys (uses ML-DSA-65 by default)<br>const { publicKey, secretKey } = generateKeyPair("ML-DSA-65");
// 2. Sign a JWT payload<br>const jwtToken = sign({ userId: 123, role: "admin" }, secretKey, {<br>expiresIn: "1h",<br>issuer: "my-app",<br>});<br>console.log("Generated JWT:", jwtToken);
// 3. Verify the token<br>try {<br>const decoded = verify(jwtToken, publicKey, { issuer: "my-app" });<br>console.log("JWT is valid!");<br>console.log("Payload:", decoded.payload);<br>} catch (error) {<br>console.log("Verification failed:", error.message);
Token Refresh (Sliding Sessions)
import { refresh } from "@pq-jwt/core";
// Automatically verifies the old token, bumps the iat and exp, and resigns<br>const newToken = refresh(oldToken, publicKey, secretKey, { expiresIn: "1h" });
Supported Algorithms
ML-DSA (Dilithium) - NIST FIPS 204
Algorithm<br>Security Level<br>Quantum Security<br>Description
ML-DSA-44<br>Level 2<br>64-bit Q<br>IoT / constrained environments
ML-DSA-65<br>Level 3<br>96-bit Q<br>General use (DEFAULT)
ML-DSA-87<br>Level 5<br>128-bit Q<br>High security / Government
SLH‑DSA (SPHINCS+) - NIST FIPS 205
Algorithm<br>Security Level<br>Quantum Security<br>Description
SLH-DSA-SHA2-128s<br>Level 1<br>64-bit Q<br>Conservative / Archival
Note: SPHINCS+ produces much larger signatures and is slower to compute, but relies on conservative hash-based assumptions rather than lattice cryptography.
Key Management & Environment Variables (.env)
One of the biggest confusions for developers switching to Post-Quantum JWTs is how to handle the massive keys. Classic JWTs (like HS256) use a simple text password (e.g., JWT_SECRET="my-super-secret") that you can easily put in your .env file.
Because ML-DSA and SLH-DSA use asymmetric cryptography , their keys are massive, mathematically-linked byte arrays (often 4KB+). You cannot generate these keys dynamically every time your server starts, or all previously issued tokens will instantly become invalid.
You handle this by generating the keys ONCE, converting them to hex, and placing them in your .env file!
Step 1: One-Time Setup Script
Run this script locally on your machine just once to generate your public and private keys, and encode them into pure strings using exportKey.
// one-time-setup.mjs<br>import { generateKeyPair, exportKey } from "@pq-jwt/core";
// Generate keys once<br>const { publicKey, secretKey } = generateKeyPair("ML-DSA-65");
// Convert huge byte arrays to safe hexadecimal strings<br>console.log("--- ADD THESE TO YOUR .env FILE ---");<br>console.log(`PQ_PRIVATE_KEY="${exportKey(secretKey)}"`);<br>console.log(`PQ_PUBLIC_KEY="${exportKey(publicKey)}"`);
Step 2: Production Server
In your production app (like Express or Next.js), you simply read those strings from your .env file and convert them back into crypto-ready keys using importKey. This makes your workflow absolutely identical to classic JWTs!
// server.mjs<br>import { importKey, sign, verify } from "@pq-jwt/core";
// 1. Load keys securely from Environment Variables!<br>const secretKey = importKey(process.env.PQ_PRIVATE_KEY);<br>const publicKey = importKey(process.env.PQ_PUBLIC_KEY);
// 2. Sign and Verify normally!<br>const token = sign({ userId: 123 }, secretKey, { expiresIn: "1h" });<br>const payload = verify(token, publicKey);
This pattern...