// kit 01

PQC Toolkit

Cripto post-cuántica lista para producción. Elige stack, elige primitiva, copia el código.

$ pqc_sign.py
L3
PYTHON
1from pqcrypto.sign import ml_dsa_65
2from nacl.signing import SigningKey, VerifyKey
3import json, time, base64
4 
5def b64(b): return base64.urlsafe_b64encode(b).rstrip(b"=").decode()
6def ub64(s): return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
7 
8class 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 pqcrypto por liboqs-python si necesitas NIST CAVP.
  • Cachea el bundle público (32 B Ed + 1952 B PQ).
  • Firma JSON canonical only.