// kit 01
PQC Toolkit
Production-ready post-quantum crypto. Pick stack, pick primitive, copy the code.
$ pqc_kem.py
L3
1 # requires: pip install pqcrypto pynacl cryptography 2 from pqcrypto.kem import ml_kem_768 3 from nacl.public import PrivateKey 4 from nacl.bindings import crypto_scalarmult 5 from cryptography.hazmat.primitives import hashes 6 from cryptography.hazmat.primitives.kdf.hkdf import HKDF 7 8 def digest(b: bytes) -> bytes: 9 h = hashes.Hash(hashes.SHA384()); h.update(b); return h.finalize() 10 11 def hybrid_keygen(): 12 pq_pub, pq_priv = ml_kem_768.generate_keypair() 13 x_priv = PrivateKey.generate() 14 return { 15 "pq_pub": pq_pub, "pq_priv": pq_priv, 16 "x_pub": bytes(x_priv.public_key), "x_priv": bytes(x_priv), 17 } 18 19 def hybrid_encaps(server_pub_pq: bytes, server_pub_x: bytes): 20 pq_ct, ss_pq = ml_kem_768.encrypt(server_pub_pq) 21 eph_priv = PrivateKey.generate() 22 eph_pub = bytes(eph_priv.public_key) 23 ss_x = crypto_scalarmult(bytes(eph_priv), server_pub_x) 24 transcript = digest(pq_ct + eph_pub) 25 session = HKDF(algorithm=hashes.SHA384(), length=32, 26 salt=transcript, info=b"qbit404-hybrid").derive(ss_x + ss_pq) 27 return {"pq_ct": pq_ct, "eph_pub": eph_pub, "session": session} 28 29 def hybrid_decaps(pq_ct: bytes, client_pub_x: bytes, pq_priv: bytes, x_priv: bytes): 30 ss_pq = ml_kem_768.decrypt(pq_priv, pq_ct) 31 ss_x = crypto_scalarmult(x_priv, client_pub_x) 32 transcript = digest(pq_ct + client_pub_x) 33 return HKDF(algorithm=hashes.SHA384(), length=32, 34 salt=transcript, info=b"qbit404-hybrid").derive(ss_x + ss_pq)
KEY SIZE
1184 B pub
SIG / CT
1088 B ct
NIST LEVEL
L3
NOTES
PQClean reference under the hood. Same hybrid construction as the Next.js version — wire-compatible.
- Threading:
generate_keypairis single-threaded; pool it. - Use
secretsandos.urandomonly. - For TLS-style use, feed
sessioninto AES-256-GCM with a per-direction nonce counter.