// kit 01
PQC Toolkit
Cripto post-cuántica lista para producción. Elige stack, elige primitiva, copia el código.
$ app/api/sign/route.ts
L3
1 import { NextResponse } from 'next/server'; 2 import { ml_dsa65 } from '@noble/post-quantum/ml-dsa'; 3 import { ed25519 } from '@noble/curves/ed25519'; 4 5 const PQ_PRIV = Buffer.from(process.env.PQ_DSA_PRIV!, 'base64'); 6 const PQ_PUB = Buffer.from(process.env.PQ_DSA_PUB!, 'base64'); 7 const ED_PRIV = Buffer.from(process.env.ED_PRIV!, 'hex'); 8 const ED_PUB = ed25519.getPublicKey(ED_PRIV); 9 10 function b64u(b: Uint8Array | Buffer) { 11 return Buffer.from(b).toString('base64url'); 12 } 13 14 export async function POST(req: Request) { 15 const claims = await req.json(); 16 const header = { alg: 'EdDSA+ML-DSA-65', typ: 'JWT-HYBRID' }; 17 const payload = { ...claims, iat: Math.floor(Date.now() / 1000) }; 18 19 const hb = b64u(Buffer.from(JSON.stringify(header))); 20 const pb = b64u(Buffer.from(JSON.stringify(payload))); 21 const msg = Buffer.from(`${hb}.${pb}`); 22 23 const sigEd = ed25519.sign(msg, ED_PRIV); 24 const sigPq = ml_dsa65.sign(msg, PQ_PRIV); 25 26 return NextResponse.json({ 27 token: `${hb}.${pb}.${b64u(sigEd)}.${b64u(sigPq)}`, 28 pub: { ed: b64u(ED_PUB), pq: b64u(PQ_PUB) }, 29 }); 30 }
TAMAÑO CLAVE
1952 B pub
FIRMA / CT
3293 B sig
NIVEL NIST
L3
NOTAS
JWT híbrido con EdDSA + ML-DSA-65. Los tokens son gordos (~6 KB codificados). Para clientes navegador, guarda el token server-side y entrega una cookie de referencia.
- Más grande que el default de cabecera de fastify o express — sube el max header size del proxy.
- Verifica ambas firmas; rechaza si cualquiera falla.
- Rota claves trimestralmente. La clave PQ también vive en un KMS.