Post-quantum ML-KEM-1024+AES-256 file encryptor (key generator, encryptor/decryptor included), file signature: KYB, file extension: .kyb
Find a file
2026-08-08 17:27:56 +00:00
decrypt.py Initial release 2026-08-08 17:27:56 +00:00
encrypt.py Initial release 2026-08-08 17:27:56 +00:00
gen_keys.py Initial release 2026-08-08 17:27:56 +00:00
README.md Initial release 2026-08-08 17:27:56 +00:00
requirements.txt Initial release 2026-08-08 17:27:56 +00:00

Post-Quantum Hybrid ML-KEM-1024 + AES-256-GCM File Encryption

Streaming hybrid file encryption: ML-KEM-1024 handles post-quantum key exchange, and AES-256-GCM handles bulk file encryption with built-in authenticity. The file signature is KYB, and the file extension is ".kyb".

Simplified flow (ML-KEM-1024 + AES-256 only, HKDF omitted for clarity):

Features

  • Post-quantum secure key exchange via liboqs ML-KEM-1024 KEM (~256-bit PQ security)
  • AES-256-GCM authenticated encryption with a streaming architecture that handles files larger than RAM (64 MB chunks)
  • AES key derived from the ML-KEM shared secret via HKDF-SHA256 (never stored in the file)
  • Unforgeable 128-bit GCM tag over the header + ciphertext to detect tampering or corruption
  • Self-describing CBOR header (RFC 8949; file signature KYB, version, algorithm and length fields), so each file identifies its own format and unsupported future versions are rejected cleanly

Requirements

python3 -m venv venv && . venv/bin/activate
pip install -r requirements.txt

Usage

  1. Generate an ML-KEM-1024 key pair
python3 gen_keys.py

Produces:

  • mlkem1024.pub - public key (1568 bytes)
  • mlkem1024.sec - secret key (3168 bytes)
  1. Encrypt a file
python3 encrypt.py archive.7z

Output: archive.7z.kyb

The .kyb file is self-contained: a compact CBOR header at the start describes the exact format, algorithms, and lengths. See File formats for the layout.

  1. Decrypt a file
python3 decrypt.py archive.7z.kyb

Output: archive.7z

The script automatically verifies the GCM tag. If the file has been tampered with, you'll see:

Error: Integrity check failed. File corrupted or tampered

and the temp file is discarded. No plaintext ever appears at the destination path until the tag has been verified.

File formats

Key files (raw binary)

File Content Size (bytes)
mlkem1024.pub ML-KEM-1024 public key 1568
mlkem1024.sec ML-KEM-1024 secret key 3168

CBOR header

Layout: 3-byte signature KYB + 1-byte version, then a CBOR map (RFC 8949) of field name → value pairs. CBOR is self-delimiting, so the reader knows exactly where the map ends; unknown keys are simply ignored, keeping the format forward-compatible. The KDF and INFO fields record the key-derivation parameters, making the file fully self-describing: with the secret key alone, a from-scratch decryptor can derive the AES key from the header.

Key Value (v1)
KEM MLKEM1024
CIPHER AES256GCM
MLKEMCT 1568
IV 12
TAG 16
KDF HKDF-SHA256
INFO mlkem-aes-key

Encrypted file structure

archive.7z.kyb:

Section Size Description
CBOR header 91 bytes (v1) Signature KYB (3 B) + version (1 B) + CBOR map (87 B)
ML-KEM ciphertext 1568 bytes Encapsulated key (ciphertext from ML-KEM-1024); length read from the header
IV (nonce) 12 bytes GCM nonce, also the HKDF salt; length read from the header
File ciphertext same as plaintext AES-256-GCM encrypted chunks, streamed in 64 MB blocks
GCM auth tag 16 bytes Tag over the header + ML-KEM CT + IV + all ciphertext; length read from the header

Security notes

  • A fresh 32-byte ML-KEM shared secret is generated per file by encap_secret() and recovered only with mlkem1024.sec via decap_secret(). It is the root key material: neither the AES key nor the ML-KEM private key.
  • The AES key is derived from that ML-KEM shared secret with HKDF-SHA256 (domain-separated info label, both recorded in the header), so no key material is ever stored in the file.
  • Because the AES key is only derivable by the legitimate recipient (ML-KEM decapsulation), the GCM tag is unforgeable: an attacker without the secret key cannot modify the file undetectably.
  • The GCM tag is computed over the CBOR header + ML-KEM CT + IV + AES ciphertext (via additional authenticated data), so any tampering with the encrypted data, the nonce, or the format header is detected before decryption.
  • Decrypted plaintext is written to a temporary file and atomically renamed into place only after the GCM tag verifies.
  • The header carries a format version; decrypt checks it up front, so a file written by a newer (or unknown) format is refused with a clear error instead of being mis-parsed.
  • ML-KEM-1024 is believed to offer security equivalent to ~256-bit classical keys against quantum attackers.
  • The secret key file (mlkem1024.sec) is the single point of failure. Losing it means losing every encrypted file. Treat it like a private SSH key: keep it offline, back it up, and restrict access (e.g. chmod 600). For stronger protection, consider encrypting the key file with a passphrase or splitting it into pieces (XOR-splitting or Shamir secret sharing) across separate locations.