mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	support encryption for files, closes #60
This commit is contained in:
		| @@ -329,7 +329,8 @@ const noteEditor = (function() { | |||||||
|         const url = new URL(window.location.href); |         const url = new URL(window.location.href); | ||||||
|         const host = url.protocol + "//" + url.hostname + ":" + url.port; |         const host = url.protocol + "//" + url.hostname + ":" + url.port; | ||||||
|  |  | ||||||
|         const downloadUrl = "/api/attachments/download/" + getCurrentNoteId(); |         const downloadUrl = "/api/attachments/download/" + getCurrentNoteId() | ||||||
|  |             + "?protectedSessionId=" + encodeURIComponent(protected_session.getProtectedSessionId()); | ||||||
|  |  | ||||||
|         return host + downloadUrl; |         return host + downloadUrl; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ const sql = require('../../services/sql'); | |||||||
| const auth = require('../../services/auth'); | const auth = require('../../services/auth'); | ||||||
| const notes = require('../../services/notes'); | const notes = require('../../services/notes'); | ||||||
| const attributes = require('../../services/attributes'); | const attributes = require('../../services/attributes'); | ||||||
|  | const protected_session = require('../../services/protected_session'); | ||||||
| const multer = require('multer')(); | const multer = require('multer')(); | ||||||
| const wrap = require('express-promise-wrap').wrap; | const wrap = require('express-promise-wrap').wrap; | ||||||
|  |  | ||||||
| @@ -44,9 +45,21 @@ router.post('/upload/:parentNoteId', auth.checkApiAuthOrElectron, multer.single( | |||||||
| router.get('/download/:noteId', auth.checkApiAuthOrElectron, wrap(async (req, res, next) => { | router.get('/download/:noteId', auth.checkApiAuthOrElectron, wrap(async (req, res, next) => { | ||||||
|     const noteId = req.params.noteId; |     const noteId = req.params.noteId; | ||||||
|     const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); |     const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||||
|  |     const protectedSessionId = req.query.protectedSessionId; | ||||||
|  |  | ||||||
|     if (!note) { |     if (!note) { | ||||||
|         return res.status(404).send(`Note ${parentNoteId} doesn't exist.`); |         return res.status(404).send(`Note ${noteId} doesn't exist.`); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (note.isProtected) { | ||||||
|  |         const dataKey = protected_session.getDataKeyForProtectedSessionId(protectedSessionId); | ||||||
|  |  | ||||||
|  |         if (!dataKey) { | ||||||
|  |             res.status(401).send("Protected session not available"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         protected_session.decryptNote(dataKey, note); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const attributeMap = await attributes.getNoteAttributeMap(noteId); |     const attributeMap = await attributes.getNoteAttributeMap(noteId); | ||||||
|   | |||||||
| @@ -88,7 +88,7 @@ function noteTitleIv(iv) { | |||||||
|     return "0" + iv; |     return "0" + iv; | ||||||
| } | } | ||||||
|  |  | ||||||
| function noteTextIv(iv) { | function noteContentIv(iv) { | ||||||
|     return "1" + iv; |     return "1" + iv; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -97,5 +97,5 @@ module.exports = { | |||||||
|     decrypt, |     decrypt, | ||||||
|     decryptString, |     decryptString, | ||||||
|     noteTitleIv, |     noteTitleIv, | ||||||
|     noteTextIv |     noteContentIv | ||||||
| }; | }; | ||||||
| @@ -148,10 +148,14 @@ async function protectNoteHistory(noteId, dataKey, protect, sourceId) { | |||||||
| async function saveNoteHistory(noteId, dataKey, sourceId, nowStr) { | async function saveNoteHistory(noteId, dataKey, sourceId, nowStr) { | ||||||
|     const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); |     const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||||
|  |  | ||||||
|  |     if (oldNote.type === 'file') { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (oldNote.isProtected) { |     if (oldNote.isProtected) { | ||||||
|         protected_session.decryptNote(dataKey, oldNote); |         protected_session.decryptNote(dataKey, oldNote); | ||||||
|  |  | ||||||
|         note.isProtected = false; |         oldNote.isProtected = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const newNoteRevisionId = utils.newNoteRevisionId(); |     const newNoteRevisionId = utils.newNoteRevisionId(); | ||||||
| @@ -217,7 +221,21 @@ async function saveNoteImages(noteId, noteText, sourceId) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function loadFile(noteId, newNote, dataKey) { | ||||||
|  |     const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||||
|  |  | ||||||
|  |     if (oldNote.isProtected) { | ||||||
|  |         await protected_session.decryptNote(dataKey, oldNote); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     newNote.detail.content = oldNote.content; | ||||||
|  | } | ||||||
|  |  | ||||||
| async function updateNote(noteId, newNote, dataKey, sourceId) { | async function updateNote(noteId, newNote, dataKey, sourceId) { | ||||||
|  |     if (newNote.detail.type === 'file') { | ||||||
|  |         await loadFile(noteId, newNote, dataKey); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (newNote.detail.isProtected) { |     if (newNote.detail.isProtected) { | ||||||
|         await protected_session.encryptNote(dataKey, newNote.detail); |         await protected_session.encryptNote(dataKey, newNote.detail); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -26,6 +26,10 @@ function getDataKey(obj) { | |||||||
|  |  | ||||||
|     const protectedSessionId = getProtectedSessionId(obj); |     const protectedSessionId = getProtectedSessionId(obj); | ||||||
|  |  | ||||||
|  |     return getDataKeyForProtectedSessionId(protectedSessionId); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function getDataKeyForProtectedSessionId(protectedSessionId) { | ||||||
|     if (protectedSessionId && session.protectedSessionId === protectedSessionId) { |     if (protectedSessionId && session.protectedSessionId === protectedSessionId) { | ||||||
|         return session.decryptedDataKey; |         return session.decryptedDataKey; | ||||||
|     } |     } | ||||||
| @@ -52,7 +56,14 @@ function decryptNote(dataKey, note) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (note.content) { |     if (note.content) { | ||||||
|         note.content = data_encryption.decryptString(dataKey, data_encryption.noteTextIv(note.noteId), note.content); |         const contentIv = data_encryption.noteContentIv(note.noteId); | ||||||
|  |  | ||||||
|  |         if (note.type === 'file') { | ||||||
|  |             note.content = data_encryption.decrypt(dataKey, contentIv, note.content); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             note.content = data_encryption.decryptString(dataKey, contentIv, note.content); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -76,7 +87,7 @@ function decryptNoteHistoryRow(dataKey, hist) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (hist.content) { |     if (hist.content) { | ||||||
|         hist.content = data_encryption.decryptString(dataKey, data_encryption.noteTextIv(hist.noteRevisionId), hist.content); |         hist.content = data_encryption.decryptString(dataKey, data_encryption.noteContentIv(hist.noteRevisionId), hist.content); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -92,19 +103,20 @@ function encryptNote(dataKey, note) { | |||||||
|     dataKey = getDataKey(dataKey); |     dataKey = getDataKey(dataKey); | ||||||
|  |  | ||||||
|     note.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(note.noteId), note.title); |     note.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(note.noteId), note.title); | ||||||
|     note.content = data_encryption.encrypt(dataKey, data_encryption.noteTextIv(note.noteId), note.content); |     note.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(note.noteId), note.content); | ||||||
| } | } | ||||||
|  |  | ||||||
| function encryptNoteHistoryRow(dataKey, history) { | function encryptNoteHistoryRow(dataKey, history) { | ||||||
|     dataKey = getDataKey(dataKey); |     dataKey = getDataKey(dataKey); | ||||||
|  |  | ||||||
|     history.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(history.noteRevisionId), history.title); |     history.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(history.noteRevisionId), history.title); | ||||||
|     history.content = data_encryption.encrypt(dataKey, data_encryption.noteTextIv(history.noteRevisionId), history.content); |     history.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(history.noteRevisionId), history.content); | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     setDataKey, |     setDataKey, | ||||||
|     getDataKey, |     getDataKey, | ||||||
|  |     getDataKeyForProtectedSessionId, | ||||||
|     isProtectedSessionAvailable, |     isProtectedSessionAvailable, | ||||||
|     decryptNote, |     decryptNote, | ||||||
|     decryptNotes, |     decryptNotes, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user