mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
server-ts: services/encryption/*.js -> ts
This commit is contained in:
parent
dc359b2a74
commit
c20d2273e6
@ -1,9 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const crypto = require('crypto');
|
import crypto = require('crypto');
|
||||||
const log = require('../log');
|
import log = require('../log');
|
||||||
|
|
||||||
function arraysIdentical(a, b) {
|
function arraysIdentical(a: Buffer, b: Buffer) {
|
||||||
let i = a.length;
|
let i = a.length;
|
||||||
if (i !== b.length) return false;
|
if (i !== b.length) return false;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
@ -12,12 +12,12 @@ function arraysIdentical(a, b) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shaArray(content) {
|
function shaArray(content: crypto.BinaryLike) {
|
||||||
// we use this as a simple checksum and don't rely on its security, so SHA-1 is good enough
|
// we use this as a simple checksum and don't rely on its security, so SHA-1 is good enough
|
||||||
return crypto.createHash('sha1').update(content).digest();
|
return crypto.createHash('sha1').update(content).digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
function pad(data) {
|
function pad(data: Buffer): Buffer {
|
||||||
if (data.length > 16) {
|
if (data.length > 16) {
|
||||||
data = data.slice(0, 16);
|
data = data.slice(0, 16);
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ function pad(data) {
|
|||||||
return Buffer.from(data);
|
return Buffer.from(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function encrypt(key, plainText) {
|
function encrypt(key: Buffer, plainText: Buffer | string) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
throw new Error("No data key!");
|
throw new Error("No data key!");
|
||||||
}
|
}
|
||||||
@ -51,10 +51,7 @@ function encrypt(key, plainText) {
|
|||||||
return encryptedDataWithIv.toString('base64');
|
return encryptedDataWithIv.toString('base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function decrypt(key: Buffer, cipherText: string | Buffer): Buffer | false | null {
|
||||||
* @returns {Buffer|false|null}
|
|
||||||
*/
|
|
||||||
function decrypt(key, cipherText) {
|
|
||||||
if (cipherText === null) {
|
if (cipherText === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -88,12 +85,12 @@ function decrypt(key, cipherText) {
|
|||||||
|
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e: any) {
|
||||||
// recovery from https://github.com/zadam/trilium/issues/510
|
// recovery from https://github.com/zadam/trilium/issues/510
|
||||||
if (e.message?.includes("WRONG_FINAL_BLOCK_LENGTH") || e.message?.includes("wrong final block length")) {
|
if (e.message?.includes("WRONG_FINAL_BLOCK_LENGTH") || e.message?.includes("wrong final block length")) {
|
||||||
log.info("Caught WRONG_FINAL_BLOCK_LENGTH, returning cipherText instead");
|
log.info("Caught WRONG_FINAL_BLOCK_LENGTH, returning cipherText instead");
|
||||||
|
|
||||||
return cipherText;
|
return Buffer.from(cipherText);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e;
|
throw e;
|
||||||
@ -101,7 +98,7 @@ function decrypt(key, cipherText) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decryptString(dataKey, cipherText) {
|
function decryptString(dataKey: Buffer, cipherText: string) {
|
||||||
const buffer = decrypt(dataKey, cipherText);
|
const buffer = decrypt(dataKey, cipherText);
|
||||||
|
|
||||||
if (buffer === null) {
|
if (buffer === null) {
|
||||||
@ -115,7 +112,7 @@ function decryptString(dataKey, cipherText) {
|
|||||||
return buffer.toString('utf-8');
|
return buffer.toString('utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
encrypt,
|
encrypt,
|
||||||
decrypt,
|
decrypt,
|
||||||
decryptString
|
decryptString
|
@ -1,28 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const optionService = require('../options.js');
|
import optionService = require('../options.js');
|
||||||
const crypto = require('crypto');
|
import crypto = require('crypto');
|
||||||
|
|
||||||
function getVerificationHash(password) {
|
function getVerificationHash(password: crypto.BinaryLike) {
|
||||||
const salt = optionService.getOption('passwordVerificationSalt');
|
const salt = optionService.getOption('passwordVerificationSalt');
|
||||||
|
|
||||||
return getScryptHash(password, salt);
|
return getScryptHash(password, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPasswordDerivedKey(password) {
|
function getPasswordDerivedKey(password: crypto.BinaryLike) {
|
||||||
const salt = optionService.getOption('passwordDerivedKeySalt');
|
const salt = optionService.getOption('passwordDerivedKeySalt');
|
||||||
|
|
||||||
return getScryptHash(password, salt);
|
return getScryptHash(password, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getScryptHash(password, salt) {
|
function getScryptHash(password: crypto.BinaryLike, salt: crypto.BinaryLike) {
|
||||||
const hashed = crypto.scryptSync(password, salt, 32,
|
const hashed = crypto.scryptSync(password, salt, 32,
|
||||||
{N: 16384, r:8, p:1});
|
{N: 16384, r:8, p:1});
|
||||||
|
|
||||||
return hashed;
|
return hashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
getVerificationHash,
|
getVerificationHash,
|
||||||
getPasswordDerivedKey
|
getPasswordDerivedKey
|
||||||
};
|
};
|
@ -1,16 +1,16 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const sql = require('../sql');
|
import sql = require('../sql');
|
||||||
const optionService = require('../options.js');
|
import optionService = require('../options.js');
|
||||||
const myScryptService = require('./my_scrypt.js');
|
import myScryptService = require('./my_scrypt.js');
|
||||||
const utils = require('../utils');
|
import utils = require('../utils');
|
||||||
const passwordEncryptionService = require('./password_encryption.js');
|
import passwordEncryptionService = require('./password_encryption.js');
|
||||||
|
|
||||||
function isPasswordSet() {
|
function isPasswordSet() {
|
||||||
return !!sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'");
|
return !!sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePassword(currentPassword, newPassword) {
|
function changePassword(currentPassword: string, newPassword: string) {
|
||||||
if (!isPasswordSet()) {
|
if (!isPasswordSet()) {
|
||||||
throw new Error("Password has not been set yet, so it cannot be changed. Use 'setPassword' instead.");
|
throw new Error("Password has not been set yet, so it cannot be changed. Use 'setPassword' instead.");
|
||||||
}
|
}
|
||||||
@ -30,7 +30,10 @@ function changePassword(currentPassword, newPassword) {
|
|||||||
|
|
||||||
const newPasswordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(newPassword));
|
const newPasswordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(newPassword));
|
||||||
|
|
||||||
|
if (decryptedDataKey) {
|
||||||
|
// FIXME: what should happen if the decrypted data key is null?
|
||||||
passwordEncryptionService.setDataKey(newPassword, decryptedDataKey);
|
passwordEncryptionService.setDataKey(newPassword, decryptedDataKey);
|
||||||
|
}
|
||||||
|
|
||||||
optionService.setOption('passwordVerificationHash', newPasswordVerificationKey);
|
optionService.setOption('passwordVerificationHash', newPasswordVerificationKey);
|
||||||
});
|
});
|
||||||
@ -40,7 +43,7 @@ function changePassword(currentPassword, newPassword) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setPassword(password) {
|
function setPassword(password: string) {
|
||||||
if (isPasswordSet()) {
|
if (isPasswordSet()) {
|
||||||
throw new Error("Password is set already. Either change it or perform 'reset password' first.");
|
throw new Error("Password is set already. Either change it or perform 'reset password' first.");
|
||||||
}
|
}
|
||||||
@ -48,13 +51,13 @@ function setPassword(password) {
|
|||||||
optionService.createOption('passwordVerificationSalt', utils.randomSecureToken(32), true);
|
optionService.createOption('passwordVerificationSalt', utils.randomSecureToken(32), true);
|
||||||
optionService.createOption('passwordDerivedKeySalt', utils.randomSecureToken(32), true);
|
optionService.createOption('passwordDerivedKeySalt', utils.randomSecureToken(32), true);
|
||||||
|
|
||||||
const passwordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(password), true);
|
const passwordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(password));
|
||||||
optionService.createOption('passwordVerificationHash', passwordVerificationKey, true);
|
optionService.createOption('passwordVerificationHash', passwordVerificationKey, true);
|
||||||
|
|
||||||
// passwordEncryptionService expects these options to already exist
|
// passwordEncryptionService expects these options to already exist
|
||||||
optionService.createOption('encryptedDataKey', '', true);
|
optionService.createOption('encryptedDataKey', '', true);
|
||||||
|
|
||||||
passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16), true);
|
passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true
|
success: true
|
@ -1,9 +1,9 @@
|
|||||||
const optionService = require('../options.js');
|
import optionService = require('../options.js');
|
||||||
const myScryptService = require('./my_scrypt.js');
|
import myScryptService = require('./my_scrypt.js');
|
||||||
const utils = require('../utils');
|
import utils = require('../utils');
|
||||||
const dataEncryptionService = require('./data_encryption.js');
|
import dataEncryptionService = require('./data_encryption.js');
|
||||||
|
|
||||||
function verifyPassword(password) {
|
function verifyPassword(password: string) {
|
||||||
const givenPasswordHash = utils.toBase64(myScryptService.getVerificationHash(password));
|
const givenPasswordHash = utils.toBase64(myScryptService.getVerificationHash(password));
|
||||||
|
|
||||||
const dbPasswordHash = optionService.getOptionOrNull('passwordVerificationHash');
|
const dbPasswordHash = optionService.getOptionOrNull('passwordVerificationHash');
|
||||||
@ -15,7 +15,7 @@ function verifyPassword(password) {
|
|||||||
return givenPasswordHash === dbPasswordHash;
|
return givenPasswordHash === dbPasswordHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDataKey(password, plainTextDataKey) {
|
function setDataKey(password: string, plainTextDataKey: string | Buffer) {
|
||||||
const passwordDerivedKey = myScryptService.getPasswordDerivedKey(password);
|
const passwordDerivedKey = myScryptService.getPasswordDerivedKey(password);
|
||||||
|
|
||||||
const newEncryptedDataKey = dataEncryptionService.encrypt(passwordDerivedKey, plainTextDataKey);
|
const newEncryptedDataKey = dataEncryptionService.encrypt(passwordDerivedKey, plainTextDataKey);
|
||||||
@ -23,8 +23,7 @@ function setDataKey(password, plainTextDataKey) {
|
|||||||
optionService.setOption('encryptedDataKey', newEncryptedDataKey);
|
optionService.setOption('encryptedDataKey', newEncryptedDataKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return {Buffer} */
|
function getDataKey(password: string) {
|
||||||
function getDataKey(password) {
|
|
||||||
const passwordDerivedKey = myScryptService.getPasswordDerivedKey(password);
|
const passwordDerivedKey = myScryptService.getPasswordDerivedKey(password);
|
||||||
|
|
||||||
const encryptedDataKey = optionService.getOption('encryptedDataKey');
|
const encryptedDataKey = optionService.getOption('encryptedDataKey');
|
||||||
@ -34,7 +33,7 @@ function getDataKey(password) {
|
|||||||
return decryptedDataKey;
|
return decryptedDataKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
verifyPassword,
|
verifyPassword,
|
||||||
getDataKey,
|
getDataKey,
|
||||||
setDataKey
|
setDataKey
|
@ -313,7 +313,7 @@ function disableSlowQueryLogging<T>(cb: () => T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
dbConnection,
|
dbConnection,
|
||||||
insert,
|
insert,
|
||||||
replace,
|
replace,
|
||||||
|
@ -41,7 +41,7 @@ function hashedBlobId(content: string) {
|
|||||||
return kindaBase62Hash.substr(0, 20);
|
return kindaBase62Hash.substr(0, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toBase64(plainText: string) {
|
function toBase64(plainText: string | Buffer) {
|
||||||
return Buffer.from(plainText).toString('base64');
|
return Buffer.from(plainText).toString('base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ function isString(x: any) {
|
|||||||
return Object.prototype.toString.call(x) === "[object String]";
|
return Object.prototype.toString.call(x) === "[object String]";
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
export = {
|
||||||
randomSecureToken,
|
randomSecureToken,
|
||||||
randomString,
|
randomString,
|
||||||
md5,
|
md5,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user