Encryption Model
The SDK encrypts and decrypts lockbox data in your browser. MDS services store ciphertext, wrapped keys, and encrypted indexes; they do not receive resource plaintext or your installation private key.
The three key layers
- The app installation key is an X25519 keypair generated locally. Vault Manager wraps a consented LEK to its public key.
- The Lockbox Encryption Key (LEK) protects every resource key in one lockbox. An open
LockboxHandleholds it temporarily in memory. - A fresh Data Encryption Key (DEK) encrypts each resource independently.
Your app never receives the user's identity private key or any key for a lockbox that was not granted to it.
Resource encryption
For each putResource() call, the SDK:
- creates a random 256-bit DEK and 12-byte IV;
- encrypts the bytes with AES-256-GCM;
- binds the resource, lockbox, and pairwise vault context as authenticated additional data (AAD);
- wraps the DEK under the LEK with AES-KW-256;
- uploads the ciphertext envelope and wrapped DEK; and
- zeroes the plaintext DEK from memory.
Binding identifiers into AAD means a ciphertext cannot be silently moved to a different resource or lockbox and still decrypt successfully.
Lockbox key wrapping
When the user approves your app, Vault Manager wraps the lockbox LEK to your installation's X25519 public key using HPKE. Only the corresponding local private key can unwrap it.
The HPKE context binds the wrap to the app id, key id, lockbox id, and pairwise vault alias. Replaying it in another context fails authentication.
Encrypted index and rollback detection
The lockbox index contains filenames, folders, expected resource versions, and ciphertext hashes. It is itself encrypted under the LEK.
On read, the SDK compares the returned metadata and ciphertext with the index. A stale version or wrong hash raises VAULT_ROLLBACK_DETECTED. Do not catch and ignore that error; stop using the returned data and report the incident.
Index writes use compare-and-set so concurrent pages cannot silently overwrite one another. Exhausted retries produce VAULT_CONFLICT.
What each party holds
| Your browser integration | MDS services |
|---|---|
| App installation private key | App installation public key |
| DPoP private key | DPoP public thumbprint and proofs |
| Unwrapped LEK while a handle is open | HPKE-wrapped LEK |
| Plaintext resource bytes while in use | Ciphertext resource envelope |
| Decrypted lockbox index while in use | Encrypted lockbox index |
Your own application code can see bytes after the SDK decrypts them. The zero-knowledge boundary protects data from MDS services; it does not protect data from scripts running with your page's authority. Keep your frontend and dependencies secure.
Algorithms and wire versions
| Layer | Algorithm | Wire version |
|---|---|---|
| Resource payload | AES-256-GCM, 12-byte IV | aes-256-gcm-v1 |
| DEK under LEK | AES-KW-256 | aes-kw-256-v1 |
| LEK to app installation | HPKE X25519 + HKDF-SHA-256 + AES-256-GCM | hpke-x25519-sha256-aes256gcm-v1 |
Wire versions are explicit. Unknown versions fail closed with a typed crypto error instead of attempting a best-effort decrypt.
Related
- App Keys & Local State — local key lifecycle.
- Storing Data — the API that drives encryption.
- Consent — when an LEK is wrapped to your app.