trilium/src/services/password.js
2021-12-30 22:54:08 +01:00

84 lines
2.6 KiB
JavaScript

"use strict";
const sql = require('./sql');
const optionService = require('./options');
const myScryptService = require('./my_scrypt');
const utils = require('./utils');
const passwordEncryptionService = require('./password_encryption');
function isPasswordSet() {
return !!sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'");
}
function changePassword(currentPassword, newPassword) {
if (!isPasswordSet()) {
throw new Error("Password has not been set yet, so it cannot be changed. Use 'setPassword' instead.");
}
if (!passwordEncryptionService.verifyPassword(currentPassword)) {
return {
success: false,
message: "Given current password doesn't match hash"
};
}
sql.transactional(() => {
const decryptedDataKey = passwordEncryptionService.getDataKey(currentPassword);
optionService.setOption('passwordVerificationSalt', utils.randomSecureToken(32));
optionService.setOption('passwordDerivedKeySalt', utils.randomSecureToken(32));
const newPasswordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(newPassword));
passwordEncryptionService.setDataKey(newPassword, decryptedDataKey);
optionService.setOption('passwordVerificationHash', newPasswordVerificationKey);
});
return {
success: true
};
}
function setPassword(password) {
if (isPasswordSet()) {
throw new Error("Password is set already. Either change it or perform 'reset password' first.");
}
optionService.createOption('passwordVerificationSalt', utils.randomSecureToken(32), true);
optionService.createOption('passwordDerivedKeySalt', utils.randomSecureToken(32), true);
const passwordVerificationKey = utils.toBase64(myScryptService.getVerificationHash(password), true);
optionService.createOption('passwordVerificationHash', passwordVerificationKey, true);
// passwordEncryptionService expects these options to already exist
optionService.createOption('encryptedDataKey', '', true);
passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16), true);
return {
success: true
};
}
function resetPassword() {
// user forgot the password,
sql.transactional(() => {
optionService.setOption('passwordVerificationSalt', '');
optionService.setOption('passwordDerivedKeySalt', '');
optionService.setOption('encryptedDataKey', '');
optionService.setOption('passwordVerificationHash', '');
});
return {
success: true
};
}
module.exports = {
isPasswordSet,
changePassword,
setPassword,
resetPassword
};