server side encryption WIP

This commit is contained in:
azivner 2017-11-12 21:40:26 -05:00
parent ec49bf0cca
commit 50b789fc39
5 changed files with 12 additions and 84 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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() {

View File

@ -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]),