Your data is end-to-end encrypted with ente. Meaning, they are encrypted with your keysbefore they leave your device.
These keys are available only to you. Meaning only you can access your data else where.
What follows is an explanation of how we do what we do.
When you sign up for ente, your client generates a masterKey for you. This never leaves your device unencrypted.
Once you choose a password, a keyEncryptionKey is derived from it. This never leaves your device.
During registration, your masterKey is encrypted with yourkeyEncryptionKey, and the resultant encryptedMasterKey is then sent to our servers for storage.
When you sign in on a secondary device, after you successfully verify your email, our servers give you back your encryptedMasterKey that was sent to us by your primary device.
You are then prompted to enter your password. Once entered, your keyEncryptionKey is derived, and the client decrypts your encryptedMasterKey with this, to yield your original masterKey.
If the decryption fails, the client will know that the derived keyEncryptionKey was wrong, indicating an incorrect password, and will surface this information to you.
keyEncryptionKey.keyEncryptionKey, only you have access to yourmasterKey.Keep reading to learn about how this masterKey is used to encrypt your data.
Each of your files in ente belong to what we call a collection. Acollection can be either a folder (like "Camera" or "Screenshots") or an album (like "Awkward Team Lunch").
Each collection has a collectionKey. These never leave your device unencrypted.
Each of your files have a fileKey. These never leave your device unencrypted.
fileKeys.fileKey is encrypted with the collectionKey of thecollection (folder/album) the file belongs to. In case such acollection does not exist, one is created with a randomly generatedcollectionKey. All collection metadata (like name, folder-path, etc) are encrypted with this collectionKey.collectionKey is then encrypted with your masterKey.collectionKey with your masterKey.fileKey with their respectivecollectionKeys.fileKeys.masterKey.masterKey, only you can decrypt thecollectionKeys.collectionKeys, only you can decrypt thefileKeys.fileKeys, only you can decrypt the files and their associated metadata.When you sign up for ente, your app generates a publicKey for you. This is public, and is stored at our servers in plain text.
Along with the publicKey, your app also generates a correspondingprivateKey for you. This never leaves your device unencrypted.
The privateKey is encrypted with your masterKey that only you have access to. This encryptedPrivateKey is stored at our servers
Sharing is similar to the previous section, except that the collectionKey of acollection is shared with a receiver after encrypting it with the receiver'spublicKey. To elaborate,
fileKeys.fileKeys were also encrypted with the collectionKeyof the collection (folder/album) that is now being shared.collectionKey is now encrypted with the publicKey of the receiver.collectionKey with theirprivateKey.fileKey with their respectivecollectionKeys.fileKeys.masterKey, only they can decrypt theirencryptedPrivateKey to access their privateKey.privateKey, only they can decrypt thecollectionKey that was sent to them.collectionKey, only they can decrypt thefileKeys of files belonging to that album/folder.fileKeys of files belonging to that album/folder, only they can decrypt the files and associated metadata.publicKey. It's technically possible for the receiver to share this information with you on a separate channel. This feature (to export and import public keys) is currently not available, and will be added if necessary. If you care about this, please upvote this feature within the "roadmap" section of the app, or email roadmap@ente.io. It will be prioritized.When you sign up for ente, your app generates a recoveryKey for you. This never leaves your device unencrypted.
Your recoveryKey and masterKey are encrypted with each other and stored on the server.
This encrypted recoveryKey is downloaded when you sign in on a new device. This is decrypted with your masterKey and surfaced to you whenever you request for it.
Post email verification, if you’re unable to unlock your account because you have forgotten your password, the client will prompt you to enter your recoveryKey.
The client then pulls the masterKey that was earlier encrypted and pushed to the server (as discussed in Key Encryption), and decrypts it with the entered recoveryKey. If the decryption succeeds, the client will know that you have entered the correct recoveryKey.
Now that you have your masterKey, the client will prompt you to set a new password, using which it will derive a new keyEncryptionKey. This is then used to encrypt yourmasterKey and this new encryptedMasterKey is uploaded to our servers, similar to what was earlier discussed in Key Encryption.
masterKey, only you can access yourrecoveryKey.recoveryKey, only you can reset your password.When you attempt to verify ownership of an email address, our server generates aoneTimeToken, that if presented confirms your access to the said email address. This token is valid for a short time and can only be used once.
When you successfully authenticate yourself against our server by proving ownership of your email (and in future any other configured vectors), the server generates anauthToken, that can from there on be used to authenticate against our private APIs.
A generated authToken is returned to your client after being encrypted with yourpublicKey. This encryptedAuthToken can only be decrypted with the yourprivateKey
oneTimeToken is sent.authToken is generated and an encryptedAuthToken is returned to you, along with your other encrypted keys.masterKey is derived (as discussed here).masterKey, the rest of your keys, including your privateKeyis decrypted (as discussed here).privateKey, the client will then decrypt theencryptedAuthToken that was encrypted by our server with yourpublicKey.authToken can then from there on be used to authenticate all API calls against our servers.Only by verifying access to your email and knowing your password can you obtain anauthToken that can be used to authenticate yourself against our servers.
We rely on the high level APIs exposed by this wonderful library called libsodium.
crypto_secretbox_keygenis used to generate all random keys within the application. YourmasterKey, recoveryKey, collectionKey, fileKeyare all 256-bit keys generated using this API.
crypto_box_keypair is used to generate yourpublicKey andprivateKey pairs.
crypto_pwhash is used to derive yourkeyEncryptionKey from your password.
crypto_pwhash_OPSLIMIT_SENSITIVE and crypto_pwhash_MEMLIMIT_SENSITIVE are used as the limits for computation and memory respectively. If the operation fails due to insufficient memory, the former is doubled and the latter is halved progressively, until a key can be derived. If during this process the memory limit is reduced to a value less thancrypto_pwhash_MEMLIMIT_MIN, the client will not let you register from that device.
Internally, this uses Argon2 v1.3, which is regarded as one of the best hashing algorithmscurrently available.
crypto_secretbox_easy is used to encrypt yourmasterKey,recoveryKey, privateKey, collectionKey s andfileKeys.
Internally, this uses XSalsa20 stream cipher with Poly1305 MAC for authentication.
crypto_secretstream_* APIs are used to encrypt your file data in chunks.
Internally, this uses XChaCha20 stream cipher with Poly1305 MAC for authentication.
crypto_box_seal is used to encrypt collectionKeyalong with the receiver's publicKey for a folder/album that is to be shared with them.
randombytes_buf is used to generate a new salt/nonce every time data needs to be hashed/encrypted.
Thank you for reading so far! For deeper implementation details, we request you to kindly checkout our ArchitectureSectionCode.
If you have any questions or concerns, or if you'd like to add yourself to the list of reviewers below, please drop an email to engineering@ente.io.
