mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	server-ts: services/encryption/*.js -> ts
This commit is contained in:
		| @@ -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)); | ||||||
|          |          | ||||||
|         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); |         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, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user