mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
server side encryption WIP
This commit is contained in:
parent
ec49bf0cca
commit
50b789fc39
@ -91,8 +91,6 @@ settings.addModule((function() {
|
||||
|
||||
// encryption password changed so current encryption session is invalid and needs to be cleared
|
||||
encryption.resetEncryptionSession();
|
||||
|
||||
encryption.setEncryptedDataKey(result.new_encrypted_data_key);
|
||||
}
|
||||
else {
|
||||
showError(result.message);
|
||||
|
@ -23,10 +23,6 @@ const encryption = (function() {
|
||||
encryptedDataKey = settings.encrypted_data_key;
|
||||
});
|
||||
|
||||
function setEncryptedDataKey(encDataKey) {
|
||||
encryptedDataKey = encDataKey;
|
||||
}
|
||||
|
||||
function setEncryptionSessionTimeout(encSessTimeout) {
|
||||
encryptionSessionTimeout = encSessTimeout;
|
||||
}
|
||||
@ -34,7 +30,7 @@ const encryption = (function() {
|
||||
function ensureEncryptionIsAvailable(requireEncryption, modal) {
|
||||
const dfd = $.Deferred();
|
||||
|
||||
if (requireEncryption && dataKey === null) {
|
||||
if (requireEncryption && !isEncryptionAvailable()) {
|
||||
// if this is entry point then we need to show the app even before the note is loaded
|
||||
showAppIfHidden();
|
||||
|
||||
@ -58,54 +54,6 @@ const encryption = (function() {
|
||||
return dfd.promise();
|
||||
}
|
||||
|
||||
async function getDataKey(password) {
|
||||
const passwordDerivedKey = await computeScrypt(password, passwordDerivedKeySalt);
|
||||
|
||||
const dataKeyAes = getDataKeyAes(passwordDerivedKey);
|
||||
|
||||
return decrypt(dataKeyAes, encryptedDataKey);
|
||||
}
|
||||
|
||||
function computeScrypt(password, salt) {
|
||||
const normalizedPassword = password.normalize('NFKC');
|
||||
const passwordBuffer = new buffer.SlowBuffer(normalizedPassword);
|
||||
const saltBuffer = new buffer.SlowBuffer(salt);
|
||||
|
||||
// this settings take ~500ms on my laptop
|
||||
const N = 16384, r = 8, p = 1;
|
||||
// 32 byte key - AES 256
|
||||
const dkLen = 32;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
scrypt(passwordBuffer, saltBuffer, N, r, p, dkLen, (error, progress, key) => {
|
||||
if (error) {
|
||||
showError(error);
|
||||
|
||||
reject(error);
|
||||
}
|
||||
else if (key) {
|
||||
resolve(key);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function decryptTreeItems() {
|
||||
if (!isEncryptionAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const noteId of glob.allNoteIds) {
|
||||
const note = treeUtils.getNodeByKey(noteId);
|
||||
|
||||
if (note.data.encryption > 0) {
|
||||
const title = decryptString(note.data.note_title);
|
||||
|
||||
note.setTitle(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setupEncryptionSession() {
|
||||
const password = encryptionPasswordEl.val();
|
||||
encryptionPasswordEl.val("");
|
||||
@ -122,6 +70,7 @@ const encryption = (function() {
|
||||
|
||||
dialogEl.dialog("close");
|
||||
|
||||
noteEditor.reload();
|
||||
noteTree.reload();
|
||||
|
||||
if (encryptionDeferred !== null) {
|
||||
@ -158,7 +107,7 @@ const encryption = (function() {
|
||||
}
|
||||
|
||||
function isEncryptionAvailable() {
|
||||
return dataKey !== null;
|
||||
return protectedSessionId !== null;
|
||||
}
|
||||
|
||||
function getDataAes() {
|
||||
@ -167,10 +116,6 @@ const encryption = (function() {
|
||||
return new aesjs.ModeOfOperation.ctr(dataKey, new aesjs.Counter(5));
|
||||
}
|
||||
|
||||
function getDataKeyAes(passwordDerivedKey) {
|
||||
return new aesjs.ModeOfOperation.ctr(passwordDerivedKey, new aesjs.Counter(5));
|
||||
}
|
||||
|
||||
function encryptNoteIfNecessary(note) {
|
||||
if (note.detail.encryption === 0) {
|
||||
return note;
|
||||
@ -307,17 +252,6 @@ const encryption = (function() {
|
||||
noteEditor.setNoteBackgroundIfEncrypted(note);
|
||||
}
|
||||
|
||||
function decryptNoteIfNecessary(note) {
|
||||
if (note.detail.encryption > 0) {
|
||||
decryptNote(note);
|
||||
}
|
||||
}
|
||||
|
||||
function decryptNote(note) {
|
||||
note.detail.note_title = decryptString(note.detail.note_title);
|
||||
note.detail.note_text = decryptString(note.detail.note_text);
|
||||
}
|
||||
|
||||
async function encryptSubTree(noteId) {
|
||||
await ensureEncryptionIsAvailable(true, true);
|
||||
|
||||
@ -433,10 +367,8 @@ const encryption = (function() {
|
||||
}, 5000);
|
||||
|
||||
return {
|
||||
setEncryptedDataKey,
|
||||
setEncryptionSessionTimeout,
|
||||
ensureEncryptionIsAvailable,
|
||||
decryptTreeItems,
|
||||
resetEncryptionSession,
|
||||
isEncryptionAvailable,
|
||||
encryptNoteIfNecessary,
|
||||
@ -444,7 +376,6 @@ const encryption = (function() {
|
||||
decryptString,
|
||||
encryptNoteAndSendToServer,
|
||||
decryptNoteAndSendToServer,
|
||||
decryptNoteIfNecessary,
|
||||
encryptSubTree,
|
||||
decryptSubTree,
|
||||
getProtectedSessionId
|
||||
|
@ -209,8 +209,6 @@ const noteEditor = (function() {
|
||||
|
||||
encryptionPasswordEl.val('');
|
||||
|
||||
encryption.decryptNoteIfNecessary(currentNote);
|
||||
|
||||
noteTitleEl.val(currentNote.detail.note_title);
|
||||
|
||||
noteChangeDisabled = true;
|
||||
@ -234,12 +232,6 @@ const noteEditor = (function() {
|
||||
async function loadNote(noteId) {
|
||||
const note = await $.get(baseApiUrl + 'notes/' + noteId);
|
||||
|
||||
if (note.detail.encryption > 0 && !encryption.isEncryptionAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
encryption.decryptNoteIfNecessary(note);
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
|
@ -190,8 +190,6 @@ const noteTree = (function() {
|
||||
|
||||
// this will also reload the note content
|
||||
await treeEl.fancytree('getTree').reload(treeResp.notes);
|
||||
|
||||
encryption.decryptTreeItems();
|
||||
}
|
||||
|
||||
function loadTree() {
|
||||
|
@ -7,6 +7,8 @@ const sql = require('../../services/sql');
|
||||
const options = require('../../services/options');
|
||||
const utils = require('../../services/utils');
|
||||
const notes = require('../../services/notes');
|
||||
const protected_session = require('../../services/protected_session');
|
||||
const data_encryption = require('../../services/data_encryption');
|
||||
|
||||
router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
|
||||
let noteId = req.params.noteId;
|
||||
@ -20,6 +22,13 @@ router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
|
||||
detail = sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
|
||||
}
|
||||
|
||||
if (detail.encryption > 0) {
|
||||
const dataKey = protected_session.getDataKey(req);
|
||||
|
||||
detail.note_title = data_encryption.decrypt(dataKey, detail.note_title);
|
||||
detail.note_text = data_encryption.decrypt(dataKey, detail.note_text);
|
||||
}
|
||||
|
||||
res.send({
|
||||
detail: detail,
|
||||
images: await sql.getResults("select * from images where note_id = ? order by note_offset", [noteId]),
|
||||
|
Loading…
x
Reference in New Issue
Block a user