Highlights
Passphrase-only encryption (v10 format). pqfile encrypt --passphrase secret.txt derives the session key straight from a passphrase via Argon2id, no key pair needed. Now available in the desktop and web GUI too, alongside the existing public key mode.
A second factor for passphrase mode. Add --keyfile (any file's SHA3-256 hash, mixed into the KDF as a pepper) or --fido2 (a physical security key's CTAP2 hmac-secret output) so decryption needs both the passphrase and the keyfile or hardware token. FIDO2 support ships in the CLI (fido2-enroll) and the desktop GUI, behind an opt-in fido2 build feature so a normal build never needs USB/hidraw libraries.
Magic-free stealth mode. encrypt --stealth produces ciphertext with no .pqf magic, version byte, or KEM variant field, so it does not identify itself as pqfile output (or as any particular key type) to an observer.
Plaintext length padding (Padme). encrypt --pad rounds the plaintext length up to a coarser bucket (12% overhead or less) so ciphertext length no longer reveals the exact file size. No wire format change: decrypt strips the padding automatically.
SLH-DSA-SHAKE-192f signatures (FIPS 205). A hash-based alternative to ML-DSA-65 for long-lived signatures, auto-detected from the key's PEM tag across sign, verify, signcrypt, and signdecrypt.
Authenticated headers. Newly written files now bind chunk_size, compression_algo, and the v10 KDF parameters into the chunk-0 key commitment, closing a gap where flipping the compression flag could smuggle compressed bytes past decryption as valid plaintext. Every file written by pqfile 4.2.4 or earlier stays readable; older pqfile versions reject the new files with a clear "unsupported version" error rather than a silent misdecrypt.
Other new commands and options: pqfile check (authenticate a file end to end without writing plaintext), doctor --calibrate (benchmark your machine and recommend Argon2id parameters), archive --recursive, compact pqf1... recipient strings plus a fingerprint subcommand, a --qr flag for terminal QR codes, a user config file for default recipient and key, and an interactive no-args CLI mode for encrypt, decrypt, and keygen.
Security and hardening
#![deny(unsafe_code)]at the crate root, with a single narrow, audited exception for memory-mapped I/O.- In-flight secrets (session keys, KEM shared secrets, Argon2id output, and more) now live in memory-locked pages, zeroized before the lock is released.
- Several small fixes: unbounded reads in older decrypt paths are now capped, private key and Shamir share files are written with owner-only permissions on Unix, Shamir shares and GUI passphrase clones are properly zeroized, and a Fisher-Yates shuffle loop is now bounded against a malfunctioning entropy source.
Performance
- zstd compression (
encrypt --compress) is now multithreaded, sized to match the existing--threadscap.
CI and supply chain
- New compatibility vectors covering v10, keyfile, stealth, and padded ciphertexts, so every wire format behavior has a frozen golden file.
cargo-semver-checksnow runs in CI and gates publishing, mechanically verifying the API stability promise inSTABILITY.md.- A daily scan for new dependency security advisories, and a
zizmoraudit of the workflow files themselves (with every finding it turned up fixed). - A permanent test proving pqfile's ML-KEM implementation and Cryspen's formally verified
libcrux-ml-kemagree byte for byte on FIPS 203, laying the groundwork for an optional verified backend.
Upgrading
No action needed for existing files or keys; everything from pqfile 4.2.4 and earlier remains fully readable. Passphrase-protected files written by untagged builds prior to this release (a narrow pre-release window) will need re-encrypting, an edge case unlikely to affect anyone running a tagged version.