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