Encrypted exports (.qenc)
Some backups belong on a USB stick or a laptop that travels. Quay’s
.qenc format is for that: the same FK-aware SQL dump, sealed
inside an authenticated-encryption envelope.
Threat model
Section titled “Threat model”.qenc protects against:
- Lost / stolen storage — a
.qencfile on a misplaced USB stick is meaningless without the passphrase. AES-256-GCM ciphertext + Argon2id-derived key. - Tampering — flipping a single byte invalidates the GCM tag; the import fails fast with a clear error rather than producing a subtly broken DB.
- Brute-force passphrases on weak hardware — Argon2id (memory-hard KDF) makes off-the-shelf GPU brute force expensive even for short passphrases.
It does not protect against:
- A passphrase you wrote on a sticky note next to the USB stick
- A keylogger on the box that creates the .qenc
- Someone shoulder-surfing while you type
File layout
Section titled “File layout”A .qenc file is a single binary blob:
[ magic "QENC\0\0\0\0" 8B ][ version u8 ][ Argon2id params: m_cost u32, t_cost u32, lanes u32 ][ salt 16B ][ nonce 12B ][ ciphertext (AES-256-GCM of the .sql payload) ][ tag 16B ]No external metadata leaks. The original filename, table count, size hints — all are inside the encrypted payload.
Passphrase suggestions
Section titled “Passphrase suggestions”When you export to .qenc, the export dialog suggests a strong
random passphrase (Diceware-style 6-word string with a “Copy”
button). You can override, but the suggestion is meant to be the
default — most users forget passphrases they pick themselves
(including the maintainer; this was a locked decision after one
too many “where did I put that backup password” support tickets).
The suggested format:
forge-quartz-meadow-spectrum-tundra-ribbon77 bits of entropy. Long enough that Argon2id-cost-amplified brute-force is unfeasible, short enough to type once.
Key derivation
Section titled “Key derivation”key = Argon2id( passphrase, salt, m_cost = 64 MiB, t_cost = 3, lanes = 4, out = 32 bytes)64 MiB memory cost is the recommended value for an interactive
“file unlock” use case. Higher costs would push restore latency on
low-RAM machines into the multi-minute range; lower costs would
weaken offline brute-force resistance. The per-file salt is fresh
random — re-encrypting the same file produces a different salt,
nonce, and ciphertext.
On wrong passphrase
Section titled “On wrong passphrase”The Argon2id derivation runs to completion before the GCM check; that’s intentional — a “wrong passphrase” check that returns in 50ms gives an attacker a fast oracle to grind against. Wrong passphrase fails the GCM tag verification, surfaces as “passphrase incorrect or file tampered” with no information about which.
Compatibility
Section titled “Compatibility”.qenc files round-trip on any platform Quay supports — file
format is byte-identical across macOS, Windows, Linux. There’s
no Quay-on-the-mainframe restore path (or anywhere else); the
file is intentionally not a portable archive format.
When NOT to use .qenc
Section titled “When NOT to use .qenc”- Production backups behind a VPN / private bucket:
.sql.gzis fine and 10× cheaper to restore. The transport is the protection. - CI fixtures: plaintext
.sqlis faster + the test runner doesn’t need passphrase juggling. - Tiny dumps (< 1 MB) that you’re handing to a colleague over Slack: 1Password / Keybase shares are simpler.
.qenc is for files at rest in lossy environments — laptops,
USB sticks, S3 buckets you don’t fully trust, archive drives you
plan to outlast in your own employment.