Last active
May 15, 2026 06:36
-
-
Save frasertweedale/975c9025fdd57160d4966b1049547507 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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