pqfile v3.0.0
Full Changelog: v2.0.5...v3.0.0
This is a major release. The .pqf file format has two new versions (v3 and v4), which are not backwards-compatible with writers from v2.x. All v2 files remain readable by v3.0.0.
Breaking changes
New default format: v3 (chunked STREAM)
Files encrypted by v3.0.0 use version byte 0x03 by default. The payload is split into 64 KiB chunks. Each chunk carries an independent AEAD tag and a position-binding counter, so truncation, reordering, and payload-swap attacks are detected before any plaintext is returned. v2.x clients cannot decrypt v3 files.
New multi-recipient format: v4
Files encrypted with multiple -r flags use version byte 0x04. v2.x clients cannot read v4 files.
New cryptographic algorithms
ML-KEM-1024 (--level 1024)
A higher security parameter set (NIST category 5, compared to category 3 for ML-KEM-768). Key generation, encryption, decryption, and inspection all support both levels. The level is embedded in the file header so decryption is automatic.
pqfile keygen --out ./keys --level 1024
Hybrid X25519+ML-KEM-768 (--hybrid)
Combines classical X25519 Diffie-Hellman with ML-KEM-768. The session key is derived via HKDF-SHA256(X25519_ss || ML-KEM_ss, info="pqfile-hybrid-v1"). Security holds if either algorithm remains unbroken, covering the transition period where quantum computers may or may not be practical.
pqfile keygen --out ./keys --hybrid
Digital signatures: ML-DSA-65 (NIST FIPS 204)
A new family of subcommands for signing and verification. Signatures are detached PEM files (3309 bytes). Signing keys are stored as a 32-byte seed.
pqfile sign-keygen --out ./keys
pqfile sign -k sign_privkey.pem document.pdf
pqfile verify -k sign_pubkey.pem -s document.pdf.sig document.pdf
New encryption features
Multi-recipient encryption
A single file can be encrypted to any number of public keys in one pass. Each recipient gets their own encapsulated session key; the file payload is encrypted once. Mixed KEM variants (768, 1024, hybrid) are supported within a single file.
pqfile encrypt -r alice/pubkey.pem -r bob/pubkey.pem secret.txt
Recursive directory encryption
Encrypts every file in a directory tree, writing .pqf files alongside the originals. Existing .pqf files are skipped.
pqfile encrypt -r pubkey.pem --recursive /path/to/dir/
Stdin / stdout pipeline support
Pass - as the input file to read from stdin. Omit -o or pass -o - to write to stdout.
cat secret.txt | pqfile encrypt -r pubkey.pem - > out.pqf
cat out.pqf | pqfile decrypt -k privkey.pem - | gpg --encrypt > double.gpg
CLI additions
Structured JSON output (--json)
Every command accepts a global --json flag. Success: {"status":"ok",...}. Errors go to stderr as {"status":"error","message":"..."}. Exit code is always 1 on error.
Shell completions
pqfile completions <shell> prints a ready-to-install script for bash, zsh, fish, PowerShell, or elvish.
pqfile completions bash >> ~/.bash_completion
pqfile completions zsh > ~/.zfunc/_pqfile
pqfile keygen --force
Without --force, keygen refuses to overwrite existing key files.
GUI improvements
Algorithm selection (Keygen tab)
Radio buttons for ML-KEM-768, ML-KEM-1024, and Hybrid X25519+ML-KEM-768.
Multi-file batch encrypt
An "Add Files" button and drag-and-drop support. Each file shows per-row status. "Encrypt All (N)" processes all files sequentially with the same recipient list.
Background threading with progress bar
Encrypt and decrypt operations run on a background thread (native). A per-file progress bar is shown during batch encrypt; a spinner is shown during decrypt. The UI stays responsive throughout.
Key management tab
A dedicated Keys tab stores remembered key pairs (label, fingerprint, directory path) across sessions. Quick-load buttons move a key directly into the Encrypt or Decrypt tab.
Passphrase field auto-show
The passphrase field in the Decrypt tab appears only when the loaded private key is passphrase-protected.
Inspect tab: multi-recipient support
Displays recipient count and per-recipient KEM variant for v4 files.
Security improvements
Passphrase protection for all key types
pqfile keygen --passphrase now works for ML-KEM-768, ML-KEM-1024, and hybrid keys. The private key seed is encrypted with AES-256-GCM using a key derived by Argon2id (m=64 MiB, t=3, p=1, 16-byte random salt).
Improved error handling in signing and decryption
Incorrect PEM tags, wrong key lengths, and unsupported version bytes now produce clear, specific errors rather than generic failures. Decryption rejects unknown version bytes before attempting any cryptographic operations.
Zeroize on drop for all new key material
The X25519 scalar, hybrid shared secrets, and ML-DSA signing key seed are all wrapped in Zeroizing<T>.
Performance
Criterion benchmark suite
pqfile/benches/crypto.rs benchmarks encrypt_bytes, decrypt_bytes, encrypt_stream, decrypt_stream, and keygen at 1 KB, 1 MB, and 100 MB. Run with cargo bench -p pqfile. HTML reports land in target/criterion/.
Streaming encryption: constant memory for large files
Peak memory use during encrypt and decrypt is proportional to the 64 KiB chunk size, not the file size.
Bug fixes
- Decryption now returns
UnsupportedVersionfor files with unrecognised version bytes, rather than misidentifying them as format errors. signandsign-keygencorrectly reject PEM blobs with the wrong tag and key material of the wrong length.
Upgrading from v2.x
No action is needed to read existing v2 files; v3.0.0 auto-detects the format version. New encryptions use the v3 streaming format by default. Library consumers using encrypt_bytes / decrypt_bytes directly continue to produce v2 output; switch to encrypt_stream / decrypt_stream for v3.
Checksums and the cosign bundle for signature verification are attached to this release. See RELEASING.md for verification instructions.