File Encryption

Encrypt a file for one recipient's ML‑KEM‑768 public key and sign it with your ML‑DSA‑65 key. Only the matching private key can open it, and the signature is checked before anything is decrypted. It all happens in your browser: the file never reaches our server.

Quantum ML-KEM-768

Encrypt & Sign

Encrypt a file for a recipient and sign it

Maximum file size: 2 MB

Select file to encrypt
Upload .key file

Files are signed with your ML‑DSA‑65 key, which lives in your vault. Create your vault to generate them

Encryption Process

  1. Kyber encapsulation creates shared secret
  2. ChaCha20‑Poly1305 encrypts file with shared secret
  3. Dilithium signs the encrypted package
  4. Everything packed into .pqc file

How File PQC Works

  1. Key Encapsulation

    ML‑KEM‑768 (Kyber) creates a shared secret using recipient's public key

  2. Encryption

    ChaCha20‑Poly1305 encrypts the file with a key derived from that shared secret (HKDF‑SHA256)

  3. Digital Signature

    ML‑DSA‑65 (Dilithium) signs the encrypted package for authenticity

  4. .pqc Package

    Everything is packaged into a secure .pqc binary file

Security Features

  • Bound to the recipient: the file key is encapsulated with ML‑KEM‑768 (FIPS 203) to the recipient's public key, so only their private key recovers it
  • FIPS 204 Compliant: Full ML-DSA signature verification
  • Authenticated Encryption: ChaCha20‑Poly1305 AEAD
  • Integrity Check: Signature verified before decryption

Requirements

  • File Size: Maximum 2 MB per file
  • For Encryption: Recipient's Kyber public key + Your Dilithium keys
  • For Decryption: Your Kyber private key + Sender's Dilithium public key
  • Key Generation: Creating your vault generates your ML‑KEM‑768 and ML‑DSA‑65 key pairs

FIPS 204 Compliance - Why Both Dilithium Keys?

FIPS 204 is the NIST standard for ML-DSA (Module-Lattice-Based Digital Signature Algorithm), formerly known as CRYSTALS-Dilithium. This standard defines how post‑quantum digital signatures must be generated and verified.

Why do we need both public AND private keys for signing?

Unlike traditional signature schemes (RSA, ECDSA) where the private key alone is sufficient, FIPS 204 ML-DSA requires the public key during signature generation for several critical reasons:

  • Signature Compression: The public key contains precomputed values (matrix A) needed to compress the signature efficiently
  • Hint Generation: ML-DSA signatures include "hints" that help verification - generating these hints requires the public key's t1 component
  • Security Proof: The NIST security proof assumes both keys are available during signing, making this a requirement for compliance
Practical Implication: When you sign a file, you must provide both your Dilithium private key (for the actual signature) and public key (for compression and hint generation). This is not a limitation of our implementation - it's a requirement of the FIPS 204 standard itself.

.pqc File Format

[4B header_len][header_json]
[4B kem_ct_len][kem_ciphertext]
[12B nonce][4B sig_len][signature]
[encrypted_data]

Binary format containing all cryptographic materials for secure file transfer

No keys yet?

Creating your vault generates your ML‑KEM‑768 and ML‑DSA‑65 key pairs. Share your public keys with the people who will send you files; your private keys stay encrypted in this browser's vault.