Sync API Docs

E2E integration flow for Sync API

Overview

This integration is aimed to track the current state of user E2E when sync, it will not fix or change E2E configurations automatically, user have to config manually if needed.

For this E2E flow, the cases are based on:

(1) Enable E2E (enable E2E on 1 device and populate E2E setup automatically through Synchronization) Device 1 turn on E2E, sync to sync target. Device 2 pick up E2E setup on next sync.
(2) Disable E2E (disable E2E on every device manually): both devices in synced with E2E on, device 1 then disable E2E and sync
(3) Changed E2E MasterKey: Assuming both devices have E2E enable properly and synced. Device 1 then change E2E key (change password) and sync.

  • In our Library, users cannot initialize an E2E setup (provide a password or toggle it on/off) because it requires proper re-encrypt and reupload data after an E2E is setup, but this library don't have much control over users' data.
  • Users can only initialize from Joplin Client (similar to sync initialization).
  • To determine which case and what actions to have, we'll start extracting from remoteSyncInfo, users should also provides last fetched E2EInfo (not provided means E2E disabled locally).
remoteE2EInfo = { 
activeMasterKeyId: string; 
ppk_: PublicPrivateKeyPair; 
e2ee: boolean; //indicate whether encryption is enable/disable  
}

localE2EInfo = { 
ppk: PublicPrivateKeyPair; 
e2ee: boolean; 
}

E2E setup flow

  • local.e2ee represents the state of our library E2E, if it's true all items are encrypted automatically before upload, other features related to E2E are also enabled.
  • Before every operations, the library will read remote and local (provided by user) sync infos, to check E2E states, and there're 4 cases below.

remote disabled, local disabled

E2E is disabled across devices, so allowing local.e2ee to false is fine

remote enabled, local disabled

Our client is the Device 2 in case (1) above, instruct user to enable local E2E, set local to remote ppk, set local masterKeyId to remote.activeMasterKeyId (will be used for encryption), prompts user to encrypt and reupload all items. Exactly like this

remote disabled, local enabled

Our client is Device 2 in case (2), instruct user to set local.e2ee to false manually, as image:

remote enabled, local enabled

-> we further check if the ppk of remote and client matched

  1. if matched, which means 2 devices are synced properly with E2E
  2. if unmatched, our client is Device 2 in case (3), instruct user to fetch the correct ppk, provides correct password for items encryption.

How E2E is applied if enabled

  • Synchronizer class hold the E2E setup infos (there's setter method for client to set), only 2 operations: CREATE and UPDATE can apply encryption, which uses the ItemUploader class, it will take the E2E input from Synchronizer and perform encryption accordingly.
  • For READ methods, client may need extra code to decrypt content with master key, because results return from Sync API will be encrypted string.