Docs / security

Vault internals

AES-256-GCM, Argon2id, machine binding, OS keychain. The full layer cake.

Last updated 2026-05-13 Edit on GitHub

The encrypted vault file is what makes QueryDen safe to trust with production credentials. This page walks the layers; for the byte-by-byte hex view, see the Security page.

The encrypted file

Path on disk:

  • Linux~/.local/share/com.queryden.app/vault.json
  • macOS~/Library/Application Support/com.queryden.app/vault.json
  • Windows%APPDATA%\com.queryden.app\vault.json

The file is binary despite the .json suffix. The layout is:

RegionSizePurpose
Magic + version6 BFile-format header, version-tagged
Salt16 BArgon2id salt — currently static, issue #14 tracks per-vault randomization
Nonce12 BAES-GCM nonce, regenerated on each write
CiphertextvariableThe encrypted vault body
MAC16 BAES-GCM authentication tag

The encryption pipeline

  1. You type a master password.
  2. QueryDen reads the machine fingerprint for your OS:
    • Linux: /etc/machine-id
    • macOS: IOPlatformUUID
    • Windows: CSP UUID
  3. The OS keychain entry for the master key is loaded (or created):
    • macOS Keychain (Secure Enclave-bound when available)
    • Windows Credential Manager (DPAPI)
    • Linux libsecret / GNOME Keyring
  4. The three inputs feed Argon2id, which derives the AES-256-GCM key.
  5. The key encrypts the vault payload. The nonce + ciphertext + MAC are written atomically.

If any single input is wrong on read — wrong password, wrong machine, missing OS keychain entry — the MAC validation fails and the file refuses to decrypt.

Brute-force lockout

Five failed unlock attempts in a row trip the lockout. The lockout duration doubles each retry. State persists across app restarts via the encrypted state file, so a relaunch doesn’t reset the counter.

What we don’t defend against

  • A rooted / compromised OS. If an attacker controls your kernel, no userland app survives.
  • A keylogger between your keyboard and your master password.
  • A network attacker between you and a database that lacks TLS. Use SSL or the SSH tunnel — that’s why they’re there.
  • You pasting a connection string in Slack. We can’t fix that.

Verify everything

The encryption code is roughly 300 lines of Rust at src-tauri/src/storage.rs. The CI pipeline that builds the binaries lives in the same repo. There is no closed-source layer.