Skip to content

Instantly share code, notes, and snippets.

@frasertweedale
Last active May 15, 2026 06:36
Show Gist options
  • Select an option

  • Save frasertweedale/975c9025fdd57160d4966b1049547507 to your computer and use it in GitHub Desktop.

Select an option

Save frasertweedale/975c9025fdd57160d4966b1049547507 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
Post-Quantum Cryptography Demo - python-cryptography 48.0.0
Demonstrates NIST-approved post-quantum algorithms:
- ML-DSA: Module-Lattice Digital Signature Algorithm
- ML-KEM: Module-Lattice Key Encapsulation Mechanism
Run with: python3 DEMO.py
"""
from cryptography.hazmat.primitives.asymmetric import mldsa, mlkem
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.exceptions import InvalidSignature
import cryptography
def pause():
input("\n>>> Press Enter to continue...")
def print_section(title):
"""Print a formatted section header."""
print(f"\n{'='*70}")
print(f" {title}")
print('='*70)
def print_step(step_num, description):
"""Print a formatted step."""
print(f"\n[Step {step_num}] {description}")
print('-' * 70)
def demo_ml_dsa():
print_section("1. ML-DSA - Post-Quantum Digital Signatures")
print_step(1, "Generate ML-DSA-65 Key Pair")
print(" private_key = mldsa.MLDSA65PrivateKey.generate()")
print(" public_key = private_key.public_key()")
private_key = mldsa.MLDSA65PrivateKey.generate()
public_key = private_key.public_key()
print(f"\n✓ Private key seed: {len(private_key.private_bytes_raw())} bytes")
print(f"✓ Public key: {len(public_key.public_bytes_raw()):,} bytes")
pause()
print_step(2, "Sign a Message")
message = b"RHEL 10 supports post-quantum cryptography!"
print(f" message = b\"{message.decode()}\"")
print(" signature = private_key.sign(message)")
signature = private_key.sign(message)
print(f"\n✓ Signature: {len(signature):,} bytes")
print(f" {signature.hex()[:64]}...")
pause()
print_step(3, "Verify the Signature")
print(" public_key.verify(signature, message)")
try:
public_key.verify(signature, message)
print("\n✓ Signature verification PASSED")
except InvalidSignature:
print("\n✗ Signature verification FAILED")
pause()
print_step(4, "Verify with Tampered Message")
tampered_message = b"RHEL 10 supports post-quantum cryptography?"
print(f" Original: ...cryptography!")
print(f" Tampered: ...cryptography?")
print(" public_key.verify(signature, tampered_message)")
try:
public_key.verify(signature, tampered_message)
print("\n✗ SECURITY ISSUE: tampered message accepted!")
except InvalidSignature:
print("\n✓ Correctly REJECTED — tampered message detected")
pause()
def demo_ml_kem():
print_section("2. ML-KEM - Post-Quantum Key Encapsulation")
print_step(1, "Recipient: Generate ML-KEM-768 Key Pair")
print(" private_key = mlkem.MLKEM768PrivateKey.generate()")
print(" public_key = private_key.public_key()")
private_key = mlkem.MLKEM768PrivateKey.generate()
public_key = private_key.public_key()
print(f"\n✓ Public key: {len(public_key.public_bytes_raw()):,} bytes")
print(" Recipient shares public key with sender...")
pause()
print_step(2, "Sender: Encapsulate")
print(" shared_secret, ciphertext = public_key.encapsulate()")
shared_secret_sender, ciphertext = public_key.encapsulate()
print(f"\n✓ Shared secret: {len(shared_secret_sender)} bytes")
print(f" {shared_secret_sender.hex()}")
print(f"✓ Ciphertext: {len(ciphertext):,} bytes")
print(f" {ciphertext.hex()[:64]}...")
print("\n Sender transmits ciphertext to recipient...")
pause()
print_step(3, "Recipient: Decapsulate")
print(" shared_secret = private_key.decapsulate(ciphertext)")
shared_secret_recipient = private_key.decapsulate(ciphertext)
print(f"\n✓ Shared secret: {len(shared_secret_recipient)} bytes")
print(f" {shared_secret_recipient.hex()}")
assert shared_secret_sender == shared_secret_recipient
print("\n✓ Both parties derived the same shared secret!")
pause()
print_step(4, "Derive AES-256 Key from Shared Secret")
print(" derived_key = HKDF(SHA256, length=32).derive(shared_secret)")
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=None,
info=b'demo-application-context',
).derive(shared_secret_sender)
print(f"\n✓ AES-256 key: {derived_key.hex()}")
print(" Ready for symmetric encryption (e.g. AES-256-GCM)")
pause()
def print_summary():
print_section("Summary")
print("""
ML-DSA (FIPS 204): quantum-safe signatures — replaces RSA/ECDSA
ML-KEM (FIPS 203): quantum-safe key exchange — replaces DH/ECDH
Levels: ML-DSA-44/65/87 ML-KEM-512/768/1024
API: from cryptography.hazmat.primitives.asymmetric import mldsa, mlkem
""")
print('='*70)
print(" Demo complete!")
print('='*70)
def print_backend_info():
print_section("Environment")
print(f" python-cryptography {cryptography.__version__}")
try:
from cryptography.hazmat.backends.openssl import backend as openssl_backend
print(f" {openssl_backend.openssl_version_text()}")
except Exception:
pass
pause()
def main():
"""Run the complete PQC demonstration."""
print("""
╔══════════════════════════════════════════════════════════════════════╗
║ ║
║ Post-Quantum Cryptography Demo ║
║ python-cryptography 48.0.0 on RHEL 10 ║
║ ║
║ Demonstrating NIST-approved quantum-safe algorithms ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
""")
print_backend_info()
try:
demo_ml_dsa()
demo_ml_kem()
print_summary()
except Exception as e:
print(f"\n❌ Error during demo: {e}")
import traceback
traceback.print_exc()
return 1
return 0
if __name__ == "__main__":
exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment