Architecture
How the encryption works.
This page is for readers who want the details: which keys exist, where each one lives, and what each side can see. If something here is unclear or looks wrong, please write to [email protected].
01Keys
Every vault has its own master key.
password ── Argon2id, 1 GiB ──► key-encryption key ─┐ ├─ wraps ─► vault master key recovery key ── Argon2id, 64 MiB ─► key-encryption key ─┘ │ wraps ▼ one random key per file, the index, a copy of the recovery key
- The vault master key is random. It leaves your device only wrapped, never in the clear.
- Your password goes through Argon2id with 1 GiB of memory, 4 passes and 4 lanes. A device with less memory uses half the memory and twice the passes, which costs the same work. The vault records the settings it was made with.
- The recovery key is 128 random bits, written as 12 words from the BIP-39 list, with a checksum that catches a wrong word. Nobody can guess 128 random bits, so its derivation can be lighter.
- The password and the recovery key each wrap the same master key, so either one opens the vault. Changing the password rewraps only the master key, not every file.
- The master key also encrypts a copy of the recovery key, so you can view it again inside the open vault.
- After an unlock, the device keeps a light copy: the master key wrapped with the password at 64 MiB of Argon2id, then sealed with the device's key. That key is in the Android Keystore on a phone, and a non-exportable Web Crypto key in a browser. The copy goes after 7 days without use, when you close the vault, or when the password changes. The copy in the cloud always keeps 1 GiB.
02Files
Each file is encrypted on its own.
- Every file gets a new random key.
- File contents are encrypted with AES-256-GCM in segments of 1 MiB (streaming AEAD, as in Google's Tink library). The order of the segments and the last segment are authenticated, so nobody can reorder, drop or cut them without the app noticing.
- Segments let a video play from the middle without decrypting the whole file first.
- File names, folders, sizes and dates are in an encrypted index. Each file on the server has a random name that says nothing about the vault, the folder or the file.
- Associated data binds each encrypted piece to its vault and its purpose, so pieces cannot be swapped between vaults.
03Who sees what
What each side can see.
| Side | Can see | Cannot see |
|---|---|---|
| Our server | Your email address, sign-in times, which vaults belong to your account, the size and time of each encrypted object. | File contents, file names, folder names, vault names, passwords, keys. |
| Storage companies | Random object names, their sizes and times, and the network address that reads or writes them. | The same as above. |
| Cloudflare, in front of our server | Your network address and the requests you make to our website and API. | The same as above. File bytes do not pass through it. |
Our server knows which vaults belong to your account so it can count them against one storage limit. No part of our API returns that list.
04On the phone
What the Android app keeps, and how.
- Each vault header is sealed with a key in the Android Keystore, in StrongBox when the phone has it. A copy of the app's storage is useless on another device.
- The app writes no plain temporary files. Viewers read decrypted data from memory.
- Every screen is marked secure, so Android leaves it out of screenshots, recordings and the recent-apps view. Other apps cannot record the audio it plays.
- Text fields ask the keyboard not to learn what you type.
- Android backup is off for vault data.
- Your home vault's key is kept sealed with the phone's key, which is why it opens with a tap on that phone.
05Phone copy off
How a vault leaves no trace on the phone.
- The phone has three slots of the same size, kept together in one file sealed with the phone's key.
- Each slot holds either a vault header, encrypted with that vault's password, or random bytes. The two look the same.
- The app seals the file again at random times, so its bytes change whether or not a vault changed.
- The three slots share one salt. One Argon2id run of a password gives a key that tries all of them, used or not, so the time says nothing about how many are in use.
- Open vault tries the vaults on the list first and the slots last. A password that opens a slot takes about as long as a wrong one.
- The vault's files and index stream from the cloud into memory. Nothing else is written to the phone.
06Sign-in
Your password never reaches us.
- A new account proves its email address with a 6-digit code, then sets a password of at least 12 characters.
- To sign in, your device runs Argon2id on the password and makes two keys from the result. One proves to our server that you know the password. The other opens your home vault. The server gets only the first one.
- The server keeps a keyed hash of that first key. Someone with a copy of our database could try passwords against it, at 1 GiB of memory per guess.
- Forgot your password? You need the email code and your recovery key. The code alone is not enough.
- A sign-in less than a day old can sign out older ones only after a code from the account's email.
- Changing the account email needs the password and a code from each address. Without the old address, the change waits 7 days, and the old address is told at once.
- In a browser, the keys of open vaults are kept for that tab only, sealed with a key the browser cannot export.
07Sync
Several devices, one vault.
- The file list of a vault is one encrypted index. Our server stores each new version and takes a change only on top of the newest one, so changes go in one at a time.
- A device whose change came second takes the newer index, puts its change on it, and tries again. Both changes stay.
- While a vault is open, the device keeps a live connection to our server. A new index version reaches the other devices at once.
- Typing in a note goes to the other devices as a small patch, sealed with the vault key. The server passes it on and keeps nothing. The saved note is an encrypted file like any other.
08Folder backup
Adding files to a locked vault.
- Each vault has an inbox key pair (X25519), made from its master key. The phone keeps only the public key.
- Each new file gets a random key and is encrypted as usual. Its name, folder and key go in an envelope sealed to the inbox public key: a one-time X25519 key, HKDF-SHA256 and AES-256-GCM, bound to the vault.
- The phone can seal files to the vault but cannot open what it sealed. Only an open vault holds the private key, and it takes the files in at the next unlock.
- A backup has a token of its own that lets it add to that one inbox and nothing else.
09Share links
A link carries its own key.
- A link is a new copy of the file, encrypted with a new random key. No vault key goes with it.
- The key is in the part of the address after
#. Browsers do not send that part to any server. - With a password, the file key is made from the link key and the password (HKDF-SHA256). Our server checks only a hash of a separate open key, and allows 10 wrong tries an hour.
- The server records the time of each download. It keeps no address and no browser.
- When the link ends, its copy is deleted within ten minutes.
10Export
Only your device decrypts an export.
- Export files decrypts on the device and writes standard ZIP files. Our server never gets a decrypted byte.
- A vault file (
.stonesafe) is a ZIP file that holds the vault header with its password and recovery key wraps, the encrypted index, and every file still encrypted. It names no cloud object and no share link. The vault's own password and recovery key open it. - The server cannot build either kind of file: it holds no vault key.
- For an emailed link, our server keeps three things until the link ends: the vault header, locked with the vault password; the list of what goes, sealed with the vault key; and the names of the encrypted files the page may read. A vault with no cloud copy uploads encrypted copies of its files for the link.
- The link's address holds a random 128-bit ID. Whoever has the address can try passwords against the header offline, as whoever had the cloud copy could. Each guess costs 1 GiB of memory.
- The page decrypts in the browser. When the link ends, after 7 days or sooner from the vault menu, the server deletes it and its copies.
11Storage
Where the bytes go.
- Encrypted files are stored with Hetzner in Helsinki, Finland. A second company can keep another copy of each file, so one company's failure does not lose your data.
- Your device sends and fetches files with short-lived signed links, straight to storage. File bytes do not pass through our API.
- When you delete a file, it goes from the main storage at once and from a copy-only storage 7 days later.
12Libraries
Built on standard pieces.
- Android encryptionGoogle Tink
- Android Argon2idthe Argon2 reference code, in C
- Web encryptionthe browser's Web Crypto, same formats
- Web Argon2idhash-wasm
- Recovery wordsBIP-39 English list
We do not write our own ciphers. The source code is not public yet.