You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-06-15 23:00:36 +02:00
All: Security: Added way to upgrade master key encryption and sync target encryption
This commit is contained in:
@ -29,7 +29,7 @@ class EncryptionService {
|
||||
this.loadedMasterKeys_ = {};
|
||||
this.activeMasterKeyId_ = null;
|
||||
this.defaultEncryptionMethod_ = EncryptionService.METHOD_SJCL_1A;
|
||||
this.defaultMasterKeyEncryptionMethod_ = EncryptionService.METHOD_SJCL_2;
|
||||
this.defaultMasterKeyEncryptionMethod_ = EncryptionService.METHOD_SJCL_4;
|
||||
this.logger_ = new Logger();
|
||||
|
||||
this.headerTemplates_ = {
|
||||
@ -107,13 +107,6 @@ class EncryptionService {
|
||||
if (!password) continue;
|
||||
|
||||
try {
|
||||
// if (mk.encryption_method != this.defaultMasterKeyEncryptionMethod_) {
|
||||
// const newMkContent = await this.generateMasterKeyContent_(password);
|
||||
// mk = Object.assign({}, mk, newMkContent);
|
||||
// await MasterKey.save(mk);
|
||||
// this.logger().info(`Master key ${mk.id} is using a deprectated encryption method. It has been upgraded to the new method.`);
|
||||
// }
|
||||
|
||||
await this.loadMasterKey_(mk, password, activeMasterKeyId === mk.id);
|
||||
} catch (error) {
|
||||
this.logger().warn(`Cannot load master key ${mk.id}. Invalid password?`, error);
|
||||
@ -229,6 +222,29 @@ class EncryptionService {
|
||||
.join('');
|
||||
}
|
||||
|
||||
masterKeysThatNeedUpgrading(masterKeys) {
|
||||
return MasterKey.allWithoutEncryptionMethod(masterKeys, this.defaultMasterKeyEncryptionMethod_);
|
||||
}
|
||||
|
||||
async upgradeMasterKey(model, decryptionPassword) {
|
||||
const newEncryptionMethod = this.defaultMasterKeyEncryptionMethod_;
|
||||
const plainText = await this.decryptMasterKey_(model, decryptionPassword);
|
||||
const newContent = await this.encryptMasterKeyContent_(newEncryptionMethod, plainText, decryptionPassword);
|
||||
return { ...model, ...newContent };
|
||||
}
|
||||
|
||||
async encryptMasterKeyContent_(encryptionMethod, hexaBytes, password) {
|
||||
// Checksum is not necessary since decryption will already fail if data is invalid
|
||||
const checksum = encryptionMethod === EncryptionService.METHOD_SJCL_2 ? this.sha256(hexaBytes) : '';
|
||||
const cipherText = await this.encrypt(encryptionMethod, password, hexaBytes);
|
||||
|
||||
return {
|
||||
checksum: checksum,
|
||||
encryption_method: encryptionMethod,
|
||||
content: cipherText,
|
||||
};
|
||||
}
|
||||
|
||||
async generateMasterKeyContent_(password, options = null) {
|
||||
options = Object.assign({}, {
|
||||
encryptionMethod: this.defaultMasterKeyEncryptionMethod_,
|
||||
@ -236,14 +252,8 @@ class EncryptionService {
|
||||
|
||||
const bytes = await shim.randomBytes(256);
|
||||
const hexaBytes = bytes.map(a => hexPad(a.toString(16), 2)).join('');
|
||||
const checksum = this.sha256(hexaBytes);
|
||||
const cipherText = await this.encrypt(options.encryptionMethod, password, hexaBytes);
|
||||
|
||||
return {
|
||||
checksum: checksum,
|
||||
encryption_method: options.encryptionMethod,
|
||||
content: cipherText,
|
||||
};
|
||||
return this.encryptMasterKeyContent_(options.encryptionMethod, hexaBytes, password);
|
||||
}
|
||||
|
||||
async generateMasterKey(password, options = null) {
|
||||
@ -259,8 +269,10 @@ class EncryptionService {
|
||||
|
||||
async decryptMasterKey_(model, password) {
|
||||
const plainText = await this.decrypt(model.encryption_method, password, model.content);
|
||||
const checksum = this.sha256(plainText);
|
||||
if (checksum !== model.checksum) throw new Error('Could not decrypt master key (checksum failed)');
|
||||
if (model.encryption_method === EncryptionService.METHOD_SJCL_2) {
|
||||
const checksum = this.sha256(plainText);
|
||||
if (checksum !== model.checksum) throw new Error('Could not decrypt master key (checksum failed)');
|
||||
}
|
||||
return plainText;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user