← Back to SolidPass
SolidPass / security internals
Zero-knowledge · on-device · offline

Inside the encryption

Your master password is the only thing that opens the vault — and it never leaves your device or gets stored anywhere. Here's exactly how a secret travels from the screen into the encrypted database, and back again.

Argon2id · memory-hard key derivation
AES-256-GCM authenticated encryption
256-bit random database key
No network permission
The workflow, both directions

The vault bridge

Press the controls to watch data move. Warm is your readable secret; cool is ciphertext on disk. Nothing is readable in the vault without the key held in memory.

Locked — key not in memory
01 Your screen
Wi-Fi password
👁 hidden
master password · typed by you
02 In memory only
Key derivationArgon2id · memory-hard
master password + salt → KEK
filling 0 MiB / 19 MiB
Database key (256-bit)— locked —
🔒
AES-256-GCMiv : ciphertext+tag
03 Encrypted vault · SQLite
metadata · encrypted_dk
2b9f…<wrapped database key>…e07a
vault_item · encrypted_details
7c14a0…f92:8ad3…<cipher>…b6
this is all that ever touches the disk
Plaintext — human-readableCiphertext — stored on diskKeys — memory only, wiped on lock
The key hierarchy

One password, two keys

Your password never encrypts data directly. It derives a wrapping key, which unlocks a random database key — the one that actually encrypts every item.

🔑
STEP 01

Master password

Known only to you. Never stored, never transmitted, never recoverable by anyone.

🧮
STEP 02 · Argon2id

Key-encryption key

Argon2id churns your password + a 32-byte random salt through a large block of memory, making brute-force attacks with GPUs or specialized hardware ruinously expensive.

🗝️
STEP 03 · AES-GCM unwrap

Database key

A random 256-bit key, itself stored only in encrypted form. The KEK unwraps it into memory.

🗂️
STEP 04

Your items

Every password, card and note is individually encrypted with the database key.

The building blocks

What's doing the work

🧮

Memory-hard by design

Argon2id (RFC 9106) turns your password into a key by working through a large block of memory, not just raw computation — so the GPU and ASIC rigs that shred older KDFs lose their edge, even offline.

Argon2id · m = 19 MiB · t = 2 passes · p = 1 · dkLen = 32 bytes · salt = 32 random bytes
🔐

Encrypt and verify

AES-256-GCM doesn't just scramble data — it attaches an authentication tag. If a single byte of the ciphertext is tampered with, decryption refuses.

256-bit key · 12-byte IV · 16-byte tag · format iv:ct+tag
🎲

Real randomness

The database key, salts and IVs come from the device's cryptographic RNG — never from your password or anything predictable.

Crypto.getRandomValues() · fresh IV per encryption
🆘

2-of-3 recovery

Three recovery codes each help wrap a spare copy of the database key. Any two, in any order, can reopen the vault if you forget your password.

SP-4K7Q
SP-B3XN
SP-M2HV
🧽

Wiped on lock

The database key lives only in RAM while the vault is open. Lock, auto-lock, or minimise, and its bytes are overwritten with zeros.

zeroize(key) · no plaintext key ever written to disk
📴

Nowhere to leak

The app ships with no internet permission at all, so encrypted or not, your data has no path off the device unless you export it yourself.

INTERNET permission stripped · zero telemetry
Ground truth

What's actually on disk

If someone copied the database file, this is all they'd see. No master password, no plaintext, no key — only a salt, the KDF settings, and ciphertext. Even item titles, types and tags are encrypted.

TableColumnStored value
metadatakdf_salta19c…<32 random bytes>…7f
metadatakdf_algorithmargon2id
metadatakdf_params{"t":2,"m":19456,"p":1}
metadataencrypted_dk3d0b…:4c8e…<database key wrapped by your password>…
metadatarecovery_dk_ab / bc / ac…<database key wrapped by each pair of recovery codes>…
vault_itemstitle / type / tags7c33…:e0a1…<AES-256-GCM ciphertext + tag>…
vault_itemsencrypted_details9f21…:8b7a…<AES-256-GCM ciphertext + tag>…
vault_itemsencrypted_notesc40e…:1d55…<ciphertext + tag>…
scanned_document_pagesencrypted_image_datab8f2…:6a4d…<ciphertext + tag>…