You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-16 00:14:34 +02:00
All: Add support for public-private key pairs and improved master password support (#5438)
Also improved SCSS support, which was needed for the master password dialog.
This commit is contained in:
@ -4,7 +4,7 @@ import Note from '../../models/Note';
|
||||
import Setting from '../../models/Setting';
|
||||
import BaseItem from '../../models/BaseItem';
|
||||
import MasterKey from '../../models/MasterKey';
|
||||
import EncryptionService from './EncryptionService';
|
||||
import EncryptionService, { EncryptionMethod } from './EncryptionService';
|
||||
import { setEncryptionEnabled } from '../synchronizer/syncInfoUtils';
|
||||
|
||||
let service: EncryptionService = null;
|
||||
@ -22,7 +22,7 @@ describe('services_EncryptionService', function() {
|
||||
|
||||
it('should encode and decode header', (async () => {
|
||||
const header = {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL,
|
||||
encryptionMethod: EncryptionMethod.SJCL,
|
||||
masterKeyId: '01234568abcdefgh01234568abcdefgh',
|
||||
};
|
||||
|
||||
@ -39,33 +39,33 @@ describe('services_EncryptionService', function() {
|
||||
|
||||
let hasThrown = false;
|
||||
try {
|
||||
await service.decryptMasterKey_(masterKey, 'wrongpassword');
|
||||
await service.decryptMasterKeyContent(masterKey, 'wrongpassword');
|
||||
} catch (error) {
|
||||
hasThrown = true;
|
||||
}
|
||||
|
||||
expect(hasThrown).toBe(true);
|
||||
|
||||
const decryptedMasterKey = await service.decryptMasterKey_(masterKey, '123456');
|
||||
const decryptedMasterKey = await service.decryptMasterKeyContent(masterKey, '123456');
|
||||
expect(decryptedMasterKey.length).toBe(512);
|
||||
}));
|
||||
|
||||
it('should upgrade a master key', (async () => {
|
||||
// Create an old style master key
|
||||
let masterKey = await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||
encryptionMethod: EncryptionMethod.SJCL2,
|
||||
});
|
||||
masterKey = await MasterKey.save(masterKey);
|
||||
|
||||
let upgradedMasterKey = await service.upgradeMasterKey(masterKey, '123456');
|
||||
let upgradedMasterKey = await service.reencryptMasterKey(masterKey, '123456', '123456');
|
||||
upgradedMasterKey = await MasterKey.save(upgradedMasterKey);
|
||||
|
||||
// Check that master key has been upgraded (different ciphertext)
|
||||
expect(masterKey.content).not.toBe(upgradedMasterKey.content);
|
||||
|
||||
// Check that master key plain text is still the same
|
||||
const plainTextOld = await service.decryptMasterKey_(masterKey, '123456');
|
||||
const plainTextNew = await service.decryptMasterKey_(upgradedMasterKey, '123456');
|
||||
const plainTextOld = await service.decryptMasterKeyContent(masterKey, '123456');
|
||||
const plainTextNew = await service.decryptMasterKeyContent(upgradedMasterKey, '123456');
|
||||
expect(plainTextOld).toBe(plainTextNew);
|
||||
|
||||
// Check that old content can be decrypted with new master key
|
||||
@ -81,15 +81,15 @@ describe('services_EncryptionService', function() {
|
||||
|
||||
it('should not upgrade master key if invalid password', (async () => {
|
||||
const masterKey = await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||
encryptionMethod: EncryptionMethod.SJCL2,
|
||||
});
|
||||
|
||||
await checkThrowAsync(async () => await service.upgradeMasterKey(masterKey, '777'));
|
||||
await checkThrowAsync(async () => await service.reencryptMasterKey(masterKey, '777', '777'));
|
||||
}));
|
||||
|
||||
it('should require a checksum only for old master keys', (async () => {
|
||||
const masterKey = await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||
encryptionMethod: EncryptionMethod.SJCL2,
|
||||
});
|
||||
|
||||
expect(!!masterKey.checksum).toBe(true);
|
||||
@ -98,33 +98,33 @@ describe('services_EncryptionService', function() {
|
||||
|
||||
it('should not require a checksum for new master keys', (async () => {
|
||||
const masterKey = await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_4,
|
||||
encryptionMethod: EncryptionMethod.SJCL4,
|
||||
});
|
||||
|
||||
expect(!masterKey.checksum).toBe(true);
|
||||
expect(!!masterKey.content).toBe(true);
|
||||
|
||||
const decryptedMasterKey = await service.decryptMasterKey_(masterKey, '123456');
|
||||
const decryptedMasterKey = await service.decryptMasterKeyContent(masterKey, '123456');
|
||||
expect(decryptedMasterKey.length).toBe(512);
|
||||
}));
|
||||
|
||||
it('should throw an error if master key decryption fails', (async () => {
|
||||
const masterKey = await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_4,
|
||||
encryptionMethod: EncryptionMethod.SJCL4,
|
||||
});
|
||||
|
||||
const hasThrown = await checkThrowAsync(async () => await service.decryptMasterKey_(masterKey, 'wrong'));
|
||||
const hasThrown = await checkThrowAsync(async () => await service.decryptMasterKeyContent(masterKey, 'wrong'));
|
||||
|
||||
expect(hasThrown).toBe(true);
|
||||
}));
|
||||
|
||||
it('should return the master keys that need an upgrade', (async () => {
|
||||
const masterKey1 = await MasterKey.save(await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||
encryptionMethod: EncryptionMethod.SJCL2,
|
||||
}));
|
||||
|
||||
const masterKey2 = await MasterKey.save(await service.generateMasterKey('123456', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL,
|
||||
encryptionMethod: EncryptionMethod.SJCL,
|
||||
}));
|
||||
|
||||
await MasterKey.save(await service.generateMasterKey('123456'));
|
||||
@ -164,22 +164,22 @@ describe('services_EncryptionService', function() {
|
||||
|
||||
{
|
||||
const cipherText = await service.encryptString('some secret', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||
encryptionMethod: EncryptionMethod.SJCL2,
|
||||
});
|
||||
const plainText = await service.decryptString(cipherText);
|
||||
expect(plainText).toBe('some secret');
|
||||
const header = await service.decodeHeaderString(cipherText);
|
||||
expect(header.encryptionMethod).toBe(EncryptionService.METHOD_SJCL_2);
|
||||
expect(header.encryptionMethod).toBe(EncryptionMethod.SJCL2);
|
||||
}
|
||||
|
||||
{
|
||||
const cipherText = await service.encryptString('some secret', {
|
||||
encryptionMethod: EncryptionService.METHOD_SJCL_3,
|
||||
encryptionMethod: EncryptionMethod.SJCL3,
|
||||
});
|
||||
const plainText = await service.decryptString(cipherText);
|
||||
expect(plainText).toBe('some secret');
|
||||
const header = await service.decodeHeaderString(cipherText);
|
||||
expect(header.encryptionMethod).toBe(EncryptionService.METHOD_SJCL_3);
|
||||
expect(header.encryptionMethod).toBe(EncryptionMethod.SJCL3);
|
||||
}
|
||||
}));
|
||||
|
||||
@ -267,12 +267,12 @@ describe('services_EncryptionService', function() {
|
||||
await service.loadMasterKey(masterKey, '123456', true);
|
||||
|
||||
// First check that we can replicate the error with the old encryption method
|
||||
service.defaultEncryptionMethod_ = EncryptionService.METHOD_SJCL;
|
||||
service.defaultEncryptionMethod_ = EncryptionMethod.SJCL;
|
||||
const hasThrown = await checkThrowAsync(async () => await service.encryptString('🐶🐶🐶'.substr(0,5)));
|
||||
expect(hasThrown).toBe(true);
|
||||
|
||||
// Now check that the new one fixes the problem
|
||||
service.defaultEncryptionMethod_ = EncryptionService.METHOD_SJCL_1A;
|
||||
service.defaultEncryptionMethod_ = EncryptionMethod.SJCL1a;
|
||||
const cipherText = await service.encryptString('🐶🐶🐶'.substr(0,5));
|
||||
const plainText = await service.decryptString(cipherText);
|
||||
expect(plainText).toBe('🐶🐶🐶'.substr(0,5));
|
||||
@ -293,4 +293,5 @@ describe('services_EncryptionService', function() {
|
||||
masterKey = await MasterKey.save(masterKey);
|
||||
expect(service.isMasterKeyLoaded(masterKey)).toBe(false);
|
||||
}));
|
||||
|
||||
});
|
||||
|
Reference in New Issue
Block a user