// kit 01
PQC Toolkit
Cripto post-cuántica lista para producción. Elige stack, elige primitiva, copia el código.
$ pqc_sign.py
L3
1 from pqcrypto.sign import ml_dsa_65 2 from nacl.signing import SigningKey, VerifyKey 3 import json, time, base64 4 5 def b64(b): return base64.urlsafe_b64encode(b).rstrip(b"=").decode() 6 def ub64(s): return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)) 7 8 class HybridSigner: 9 def __init__(self, ed_seed: bytes, pq_pub: bytes, pq_priv: bytes): 10 self.ed = SigningKey(ed_seed) 11 self.pq_pub, self.pq_priv = pq_pub, pq_priv 12 13 @classmethod 14 def fresh(cls): 15 from os import urandom 16 pq_pub, pq_priv = ml_dsa_65.generate_keypair() 17 return cls(urandom(32), pq_pub, pq_priv) 18 19 def issue(self, claims: dict) -> str: 20 header = {"alg": "EdDSA+ML-DSA-65", "typ": "JWT-HYBRID"} 21 payload = {**claims, "iat": int(time.time())} 22 hb = b64(json.dumps(header, separators=(",", ":")).encode()) 23 pb = b64(json.dumps(payload, separators=(",", ":")).encode()) 24 msg = f"{hb}.{pb}".encode() 25 sed = self.ed.sign(msg).signature 26 spq = ml_dsa_65.sign(self.pq_priv, msg) 27 return f"{hb}.{pb}.{b64(sed)}.{b64(spq)}" 28 29 def verify(self, token: str): 30 try: 31 h, p, s_ed, s_pq = token.split(".") 32 msg = f"{h}.{p}".encode() 33 VerifyKey(bytes(self.ed.verify_key)).verify(msg, ub64(s_ed)) 34 ml_dsa_65.verify(self.pq_pub, msg, ub64(s_pq)) 35 return json.loads(ub64(p)) 36 except Exception: 37 return None
TAMAÑO CLAVE
1952 B pub
FIRMA / CT
3293 B sig
NIVEL NIST
L3
NOTAS
Misma forma en cable que el emisor Next.js.
- Cambia
pqcryptoporliboqs-pythonsi necesitas NIST CAVP. - Cachea el bundle público (32 B Ed + 1952 B PQ).
- Firma JSON canonical only.