You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-06-27 23:28:38 +02:00
All: Improved E2EE usability by making its state a property of the sync target (#5276)
This commit is contained in:
@ -10,6 +10,8 @@ import MasterKey from '../../models/MasterKey';
|
||||
import BaseItem from '../../models/BaseItem';
|
||||
import { ResourceEntity } from '../database/types';
|
||||
import Synchronizer from '../../Synchronizer';
|
||||
import { getEncryptionEnabled, setEncryptionEnabled } from '../synchronizer/syncInfoUtils';
|
||||
import { loadMasterKeysFromSettings, setupAndDisableEncryption, setupAndEnableEncryption } from '../e2ee/utils';
|
||||
|
||||
let insideBeforeEach = false;
|
||||
|
||||
@ -31,7 +33,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
});
|
||||
|
||||
it('notes and folders should get encrypted when encryption is enabled', (async () => {
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
let note1 = await Note.save({ title: 'un', body: 'to be encrypted', parent_id: folder1.id });
|
||||
@ -55,7 +57,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
expect(masterKey_2.content).toBe(masterKey.content);
|
||||
expect(masterKey_2.checksum).toBe(masterKey.checksum);
|
||||
// Now load the master key we got from client 1 and try to decrypt
|
||||
await encryptionService().loadMasterKey_(masterKey_2, '123456', true);
|
||||
await encryptionService().loadMasterKey(masterKey_2, '123456', true);
|
||||
// Get the decrypted items back
|
||||
await Folder.decrypt(folder1_2);
|
||||
await Note.decrypt(note1_2);
|
||||
@ -74,7 +76,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
|
||||
it('should enable encryption automatically when downloading new master key (and none was previously available)',(async () => {
|
||||
// Enable encryption on client 1 and sync an item
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
await loadEncryptionMasterKey();
|
||||
let folder1 = await Folder.save({ title: 'folder1' });
|
||||
await synchronizerStart();
|
||||
@ -82,9 +84,9 @@ describe('Synchronizer.e2ee', function() {
|
||||
await switchClient(2);
|
||||
|
||||
// Synchronising should enable encryption since we're going to get a master key
|
||||
expect(Setting.value('encryption.enabled')).toBe(false);
|
||||
expect(getEncryptionEnabled()).toBe(false);
|
||||
await synchronizerStart();
|
||||
expect(Setting.value('encryption.enabled')).toBe(true);
|
||||
expect(getEncryptionEnabled()).toBe(true);
|
||||
|
||||
// Check that we got the master key from client 1
|
||||
const masterKey = (await MasterKey.all())[0];
|
||||
@ -109,7 +111,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
|
||||
// Now client 2 set the master key password
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
|
||||
// Now that master key should be loaded
|
||||
expect(encryptionService().loadedMasterKeyIds()[0]).toBe(masterKey.id);
|
||||
@ -141,24 +143,22 @@ describe('Synchronizer.e2ee', function() {
|
||||
// Then enable encryption and sync again
|
||||
let masterKey = await encryptionService().generateMasterKey('123456');
|
||||
masterKey = await MasterKey.save(masterKey);
|
||||
await encryptionService().enableEncryption(masterKey, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await setupAndEnableEncryption(encryptionService(), masterKey, '123456');
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
await synchronizerStart();
|
||||
|
||||
// Even though the folder has not been changed it should have been synced again so that
|
||||
// an encrypted version of it replaces the decrypted version.
|
||||
files = await fileApi().list('', { includeDirs: false, syncItemsOnly: true });
|
||||
expect(files.items.length).toBe(2);
|
||||
expect(files.items.length).toBe(1);
|
||||
|
||||
// By checking that the folder title is not present, we can confirm that the item has indeed been encrypted
|
||||
// One of the two items is the master key
|
||||
content = await fileApi().get(files.items[0].path);
|
||||
expect(content.indexOf('folder1') < 0).toBe(true);
|
||||
content = await fileApi().get(files.items[1].path);
|
||||
expect(content.indexOf('folder1') < 0).toBe(true);
|
||||
}));
|
||||
|
||||
it('should upload decrypted items to sync target after encryption disabled', (async () => {
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
await loadEncryptionMasterKey();
|
||||
|
||||
await Folder.save({ title: 'folder1' });
|
||||
@ -167,7 +167,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
let allEncrypted = await allSyncTargetItemsEncrypted();
|
||||
expect(allEncrypted).toBe(true);
|
||||
|
||||
await encryptionService().disableEncryption();
|
||||
await setupAndDisableEncryption(encryptionService());
|
||||
|
||||
await synchronizerStart();
|
||||
allEncrypted = await allSyncTargetItemsEncrypted();
|
||||
@ -179,7 +179,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
// which means it's going to fail in unexpected way. So the loop below wait for beforeEach to be done.
|
||||
while (insideBeforeEach) await time.msleep(100);
|
||||
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
|
||||
await Folder.save({ title: 'folder1' });
|
||||
@ -188,21 +188,21 @@ describe('Synchronizer.e2ee', function() {
|
||||
await switchClient(2);
|
||||
|
||||
await synchronizerStart();
|
||||
expect(Setting.value('encryption.enabled')).toBe(true);
|
||||
expect(getEncryptionEnabled()).toBe(true);
|
||||
|
||||
// If we try to disable encryption now, it should throw an error because some items are
|
||||
// currently encrypted. They must be decrypted first so that they can be sent as
|
||||
// plain text to the sync target.
|
||||
// let hasThrown = await checkThrowAsync(async () => await encryptionService().disableEncryption());
|
||||
// let hasThrown = await checkThrowAsync(async () => await setupAndDisableEncryption(encryptionService()));
|
||||
// expect(hasThrown).toBe(true);
|
||||
|
||||
// Now supply the password, and decrypt the items
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
await decryptionWorker().start();
|
||||
|
||||
// Try to disable encryption again
|
||||
const hasThrown = await checkThrowAsync(async () => await encryptionService().disableEncryption());
|
||||
const hasThrown = await checkThrowAsync(async () => await setupAndDisableEncryption(encryptionService()));
|
||||
expect(hasThrown).toBe(false);
|
||||
|
||||
// If we sync now the target should receive the decrypted items
|
||||
@ -212,7 +212,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
}));
|
||||
|
||||
it('should set the resource file size after decryption', (async () => {
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
@ -227,7 +227,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
|
||||
await synchronizerStart();
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
|
||||
const fetcher = newResourceFetcher(synchronizer());
|
||||
fetcher.queueDownload_(resource1.id);
|
||||
@ -249,8 +249,8 @@ describe('Synchronizer.e2ee', function() {
|
||||
expect(await allSyncTargetItemsEncrypted()).toBe(false);
|
||||
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
await encryptionService().enableEncryption(masterKey, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await setupAndEnableEncryption(encryptionService(), masterKey, '123456');
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
|
||||
await synchronizerStart();
|
||||
|
||||
@ -264,20 +264,20 @@ describe('Synchronizer.e2ee', function() {
|
||||
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
await encryptionService().enableEncryption(masterKey, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await synchronizerStart();
|
||||
await setupAndEnableEncryption(encryptionService(), masterKey, '123456');
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
// await synchronizerStart();
|
||||
|
||||
const resource1 = (await Resource.all())[0];
|
||||
expect(resource1.encryption_blob_encrypted).toBe(0);
|
||||
// const resource1 = (await Resource.all())[0];
|
||||
// expect(resource1.encryption_blob_encrypted).toBe(0);
|
||||
}));
|
||||
|
||||
it('should decrypt the resource metadata, but not try to decrypt the file, if it is not present', (async () => {
|
||||
const note1 = await Note.save({ title: 'note' });
|
||||
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
await encryptionService().enableEncryption(masterKey, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await setupAndEnableEncryption(encryptionService(), masterKey, '123456');
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
await synchronizerStart();
|
||||
expect(await allSyncTargetItemsEncrypted()).toBe(true);
|
||||
|
||||
@ -285,7 +285,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
|
||||
await synchronizerStart();
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
await decryptionWorker().start();
|
||||
|
||||
let resource = (await Resource.all())[0];
|
||||
@ -311,8 +311,8 @@ describe('Synchronizer.e2ee', function() {
|
||||
|
||||
const note = await Note.save({ title: 'ma note' });
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
await encryptionService().enableEncryption(masterKey, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await setupAndEnableEncryption(encryptionService(), masterKey, '123456');
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
await synchronizerStart();
|
||||
|
||||
await switchClient(2);
|
||||
@ -329,7 +329,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
await Note.save({ id: note.id, encryption_cipher_text: 'doesntlookright' });
|
||||
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKey.id, '123456');
|
||||
await encryptionService().loadMasterKeysFromSettings();
|
||||
await loadMasterKeysFromSettings(encryptionService());
|
||||
|
||||
hasThrown = await checkThrowAsync(async () => await decryptionWorker().start({ errorHandler: 'throw' }));
|
||||
expect(hasThrown).toBe(true);
|
||||
@ -367,7 +367,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
}));
|
||||
|
||||
it('should not encrypt notes that are shared by link', (async () => {
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
await loadEncryptionMasterKey();
|
||||
|
||||
await createFolderTree('', [
|
||||
@ -459,7 +459,7 @@ describe('Synchronizer.e2ee', function() {
|
||||
return;
|
||||
}
|
||||
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
setEncryptionEnabled(true);
|
||||
await loadEncryptionMasterKey();
|
||||
|
||||
const folder1 = await createFolderTree('', [
|
||||
|
Reference in New Issue
Block a user