Zero-knowledge sync
1. Goal, stated honestly
"Unhackable" is not a property anyone can promise. What we can build is a backend that holds nothing worth hacking: the sync service is a store of opaque encrypted blobs.
The server can see that an account exists, when it syncs, how many records and photos it holds and roughly how big they are, how many devices are enrolled, and the connecting IP address.
The server cannot see any field of any record, what kind of record a blob is (barrel, load, session...), your name or email, your password, or your photos.
2. Everything is encrypted on the device
- Each account has one random 256-bit root key, generated on the first device and never sent anywhere in the clear.
- Separate sub-keys for records and photos are derived from the root key with HKDF-SHA256.
- Each record is serialised (its type travels inside the ciphertext) and sealed with AES-256-GCM via Apple CryptoKit, with a fresh random 96-bit nonce on every write.
- The record's id and its sync timestamps are bound in as authenticated data, so the server cannot move a ciphertext to another id or rewind its timestamps without decryption failing on your device.
- Plaintext is padded to the next 256-byte boundary so blob sizes don't reveal record types.
- Photos are sealed the same way under their own sub-key. Each photo's id is a random UUID stored inside the encrypted target record, so the server cannot even pair a photo with a record.
3. The server stores blobs, not tables
Synced data lives in a single table:
blobs(id, user_id, updated_at, deleted_at, server_seq, key_version, ciphertext)
Sync is last-writer-wins on updated_at with a per-account sequence cursor. The server validates only shapes and sizes (id format, integer timestamps, ciphertext up to 64 KB, at most 2,000 rows and 8 MB per request) and has no idea what it is syncing.
4. Moving the key between your devices
A second phone or an iPad can read your data only once it has the root key. There are three ways to get it there, none of which hand the key to us.
Approve from a device you already have
- Each install generates a P-256 key-agreement pair in the Secure Enclave (where the hardware has one). The private key never leaves the chip. Only the public key is registered with the server.
- When a new device signs in, it shows a six-digit approval code derived from a SHA-256 hash of its public key. An enrolled device computes the same code from the public key the server relayed. If the codes match, you approve.
- Because the code is tied to the public key itself, a malicious server cannot slip in its own key without the codes disagreeing.
- The approving device wraps the root key to the newcomer's public key (ephemeral ECDH, HKDF-SHA256, AES-256-GCM) and uploads that wrapped copy. The wrap is bound to the device id and key version, so the server cannot re-file it under another device.
Exported key file
Settings → Encryption → Export Encryption Key saves the root key as a file you keep, for example in a password manager. Importing it on another device installs the key directly. This is also the recovery path if you ever have no enrolled device left.
iCloud Keychain (optional)
If you turn it on, the root key is stored as a synchronizable Keychain item and Apple's end-to-end encrypted iCloud Keychain carries it to your other Apple devices. Nothing goes to our server.
5. Removing a device
Revoking a device (Settings → Encryption → Devices) does more than sign it out. Because a removed device may have kept a copy of the key, the app:
- Syncs everything, so the revoking phone has the latest state.
- Deletes the device, its wrapped key and every session bound to it on the server. Its next request fails and it is signed out.
- Generates a fresh root key and wraps it to every remaining device.
- Re-encrypts and re-uploads every photo and record under the new key. A photo that cannot be re-sealed is deleted rather than left under the retired key.
Every sync request declares the device's key version, and the server refuses one that is behind the account, so your other devices pick up the new key automatically before syncing again.
6. Accounts that know as little as possible
- Email and Apple user identifier are stored only as HMAC-SHA256 under a server-side secret: enough to find your account, unrecoverable from the database alone. No display name is stored. Sign in with Apple's Hide My Email works as well.
- For email accounts, the app runs PBKDF2-SHA256 (600,000 rounds) over your password on the phone and sends only the derived key. The server salts and hashes that again. Your actual password never crosses the wire.
- Session tokens are random, stored hashed, last 30 days with sliding renewal, and are bound to a device so revoking the device ends its sessions. "Sign out everywhere" is available.
7. Hardening
- Server. No CORS.
cache-control: no-storeand HSTS on every response. Errors return a generic message with no internals. Rate limits per IP on sign-in and per account on sync and photos. Size caps on every request. Logs never include request bodies, tokens or key material. - Device. The root key lives in the Keychain, accessible after first unlock and bound to the device unless you opt into iCloud Keychain. The device private key is Secure Enclave–backed and usable only while unlocked. Decryption failures are surfaced, never silently skipped.
8. What this does not defend against
- A compromised device. A jailbroken or malware-infected phone, or a tampered build of the app. The device is the root of trust.
- Losing everything at once. If you lose every enrolled device and your exported key file, the server copy is unrecoverable by design. The data on any phone you still have stays readable, and you can replace the server copy from it.
- Traffic analysis. Sync timing, blob counts and approximate sizes are visible to the server.
9. Questions and reports
If you think you've found a weakness, email support@invictusarmory.com. We read every report.