Documentation
Guides
End-to-end encrypted backups

End-to-end encrypted backups

The main idea behind it is to be able to to encrypt any kind of data locally and then upload it to the server for it to be retrieved later.

While a simple sodium.crypto_secretbox_easy could do the trick here we are introducing a version that offers two extra features and properties:

  • allow to create a recovery token that can be used to recover the data in case the user loses the password
  • the server should be able to verify the authenticity of the data send by the client based on the session_key

Default Workflows

Create and store the Locker

// client session 1
 
// 1. login via opaque and get the export and session key
// 2. create a locker
const locker = createLocker({
  // can be a string or a Uint8Array
  data: JSON.stringify({ notes: ["What a great day"] }),
  exportKey,
  sessionKey,
});
// 3. send the locker to the server
// server
 
// 1. validate the locker and decrypt the publicAdditionalData
const isValid = isValidLocker({
  locker,
  sessionKey,
});
// 2. store the locker in the DB
const storyEntry = {
  ciphertext: locker.ciphertext,
  nonce: locker.nonce,
  userId: "abc", // so we can identify who the locker belongs to
};

Retrieve and decrypt the Locker

// client
// 1. login via opaque and get the export and session key
// server
// 1. get the ciphertext and nonce from the DB
const locker = {
  ciphertext: storyEntry.ciphertext,
  nonce: storyEntry.nonce,
};
// 2. send the locker to the client
// client
// 1. decrypt the locker
const data = decryptLocker({
  locker,
  exportKey,
});

Example

Endpoints

  • POST /api/locker/store - create a locker
  • GET /api/locker/retrieve - retrieve the user's locker

Whenever a new locker is created it overwrites the old one.

In the DB we store the following fields:

  • ciphertext
  • nonce
  • publicAdditionalData
  • userId

Formal Proofs