Security Architecture

How Snoq Encrypts Your Notes

AES-256-CBC with HMAC-SHA256, Argon2id key derivation, per-note random IVs. No passwords, keys, or plaintext ever leave your device.

AES-256-CBC
HMAC-SHA256
Argon2id
100% Local

What happens when you type a note

When encryption is enabled and you save a note, Snoq encrypts the content with AES-256 before it ever touches your disk. The key used for encryption is not your password — it is derived from your password through Argon2id, a modern, memory-hard key-derivation function specifically designed to make brute-force attacks expensive.

Every note gets its own random 16-byte initialization vector (IV), so two notes with identical content produce completely different ciphertext. Each encrypted note is then authenticated with HMAC-SHA256, so any tampering — even a single flipped bit — is detected before decryption is even attempted.

None of this is theoretical. It's how every note is stored, right now, on your machine. The rest of this page describes exactly how — in enough detail that a security-minded reader can verify the approach is sound.

What Snoq never stores

Three things are deliberately absent from disk — and from memory once the app is locked.

  • Your password — in any form. Not plaintext, not a reversible hash, not anywhere. What Snoq stores is an Argon2id verifier, which can confirm a guess is correct but cannot be used to recover the password or the encryption keys.
  • The derived AES or HMAC keys. When Snoq is locked, both key buffers are zeroed in memory (Array.Clear) and the references are nulled. Nothing is cached, swapped intentionally, or persisted.
  • Plaintext note content. When encryption is on, the local database only ever contains ciphertext. Plaintext exists briefly in memory while you're actively reading or editing a note, and is discarded afterward.

Cryptographic primitives

The exact algorithms and parameters Snoq uses. All are standard, well-reviewed constructions.

Purpose Algorithm Parameters
Password verification Argon2id 64 MB memory, 2 threads, 3 iterations, 32-byte output
Key derivation Argon2id 64 MB memory, 2 threads, 3 iterations, 32-byte salt, 64-byte output split into enc + MAC keys, domain-prefixed password
Note encryption AES-256-CBC Random 16-byte IV per note
Authentication HMAC-SHA256 Covers IV + ciphertext (Encrypt-then-MAC)
Salt generation RandomNumberGenerator 32 bytes from OS CSPRNG

Argon2id is the RFC 9106 standard for password-based key derivation and the winner of the Password Hashing Competition.

How a single encrypted note is laid out

Each note stored in the database looks like this — a Base64-encoded blob of three concatenated pieces.

Ciphertext layout (per note)
IV
16 bytes
Random per note
HMAC
32 bytes
SHA-256 tag
AES-CBC Ciphertext
N bytes
Encrypted Quill Delta JSON

Encrypt-then-MAC. The HMAC is computed over IV || ciphertext and verified before any decryption is attempted. If the tag doesn't match — wrong key, corruption, tampering — the note is rejected with no plaintext exposure. This avoids padding-oracle attacks that can affect CBC mode when authentication is missing or done incorrectly.

The unlock flow

What happens when you type your password to open your notes.

  1. 1
    Fast pre-check. The dialog runs Argon2id against the stored password verifier. If it doesn't match, the attempt is rejected immediately — nothing else happens.
  2. 2
    Derive keys. Argon2id runs again — this time with a domain prefix (snoq-enc:) to produce 64 bytes of key material, split into a 32-byte AES key and a 32-byte HMAC key.
  3. 3
    Verify the canary. A small known blob — encrypted with the real keys when the password was first set — is decrypted with the freshly derived keys and compared to its expected value in constant time. This proves the derived keys match the ones used to encrypt your notes, independently of the verifier.
  4. 4
    Canary fails? The freshly derived keys are zeroed, and the unlock is rejected. Any existing unlocked session is untouched.
  5. 5
    Canary passes? The keys are stored in memory (byte arrays, nowhere else) and notes become readable. From this moment, every read decrypts on demand; every write encrypts on demand.

Why two Argon2id runs?

The verifier and the encryption keys are derived with different inputs (the encryption path prepends snoq-enc: to the password before hashing). This is called domain separation: even though both paths use the same password and salt, their outputs are completely unrelated. An attacker who somehow learned the verifier would still have nothing useful for decrypting notes.

Changing your password safely

Re-encrypting an entire vault is a risky operation — if it fails halfway, some notes would be stuck with the old key and some with the new. Snoq avoids that with a stage-then-commit pattern.

1

Stage in memory

Every encrypted note is decrypted with the old keys and re-encrypted with the new keys — entirely in memory. If the old password is wrong, HMAC verification fails on the very first note, an exception is raised, and nothing is written to disk.

2

Commit to disk

Only if every note re-encrypted successfully does Snoq walk the staged list and write the updated notes to the database. A mid-operation failure leaves the original vault fully intact.

Security FAQ

There is no recovery mechanism — and that's by design. Your password is the only input from which the encryption keys can be derived. Snoq never stores it, never transmits it, and has no backdoor. If the password is lost, the notes cannot be decrypted. Please keep your password in a safe place, like a password manager.

Snoq uses AES-256-CBC combined with HMAC-SHA256 in an Encrypt-then-MAC construction. When implemented correctly — random IV per message, HMAC over IV+ciphertext, constant-time verification before any decryption — this provides authenticated encryption equivalent in security to AES-GCM, with broader cross-platform library support. The important property is authentication, and Snoq authenticates every note.

No. Derived keys live only in memory as byte arrays inside the encryption service. When Snoq is locked (manually, via the UI lock hotkey, or automatically), both the AES key and the HMAC key are zeroed with Array.Clear and their references are nulled. We can't promise the OS will never page memory to disk under extreme pressure — no user-space app can — but Snoq never intentionally persists keys.

No. The verifier and the encryption keys are produced by two different Argon2id runs with different inputs (the encryption path prepends a domain-separation prefix to the password before hashing). Even though both use the same salt, their outputs are completely unrelated. An attacker who copied the verifier from your settings file has gained no information usable for decryption — they'd still need to brute-force the password itself.

Snoq exports your vault as an encrypted zip archive. The export retains the encryption, so a backup dropped on a USB stick or cloud drive remains safe. On restore, you'll need your password to decrypt it — the same security model as the local vault.

No. There is no cloud sync, no telemetry, no crash reporting, and no account system. Snoq checks for its own updates, but note content, passwords, and usage patterns never leave your machine. You can verify this with any network monitor.

Ready to try it?

Snoq is free, installs in seconds, and never asks for an account.

Download Snoq for Windows