From 084e52be15b85e54948435cafcc22d24373600e5 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Wed, 10 Sep 2025 20:58:10 -0400 Subject: [PATCH] Wrapping up for the night. Lots of work on encryption related. --- src/lib/ae_utils/ae_utils__crypto.ts | 1 + .../entry/[journal_entry_id]/+page.svelte | 2 +- .../ae_comp__journal_entry_obj_id_view.svelte | 352 +++++++++--------- 3 files changed, 171 insertions(+), 184 deletions(-) diff --git a/src/lib/ae_utils/ae_utils__crypto.ts b/src/lib/ae_utils/ae_utils__crypto.ts index 7da5c314..81cb366d 100644 --- a/src/lib/ae_utils/ae_utils__crypto.ts +++ b/src/lib/ae_utils/ae_utils__crypto.ts @@ -104,6 +104,7 @@ export let decrypt_wrapper = async function decrypt_wrapper( return false; } const { iv, base64 } = split_iv_and_base64(combined); + console.log(`IV: ${iv}; Encrypted:`, base64); let decrypted; try { decrypted = await decrypt_content(base64, iv, keyData); diff --git a/src/routes/journals/[journal_id]/entry/[journal_entry_id]/+page.svelte b/src/routes/journals/[journal_id]/entry/[journal_entry_id]/+page.svelte index c3fcb785..47852b72 100644 --- a/src/routes/journals/[journal_id]/entry/[journal_entry_id]/+page.svelte +++ b/src/routes/journals/[journal_id]/entry/[journal_entry_id]/+page.svelte @@ -187,7 +187,7 @@ let lq__journal_entry_obj = $derived(liveQuery(async () => { $effect(() => { if (browser && $lq__journal_entry_obj?.journal_entry_id) { - log_lvl = 2; + // log_lvl = 2; // Start with the current KV or convert the LI to a KV if needed let history_kv = { ...( $journals_loc?.entry_view_history_kv ?? {} ) }; diff --git a/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte b/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte index c7cfe017..7d4292d8 100644 --- a/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte +++ b/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte @@ -109,6 +109,17 @@ let updated_idb: boolean = $state(true); // Updated in a separate browser sessio +let journal_key = $derived(() => { + return $lq__journal_obj?.combined_passcode || $lq__journal_obj?.passcode || 'temp-secret-key'; +}); +// let journal_key = $state($lq__journal_obj?.combined_passcode || $lq__journal_obj?.passcode || 'temp-secret-key'); + +let content = ''; // "This is my test content to encrypt and decrypt."; +let encrypted_base64_string: string = $state(''); +let encryption_iv: null|Uint8Array = $state(null); +let decrypted_content: string = $state(''); +let trigger_decrypt: boolean = $state(false); +let decrypted_history: string = $state(''); if (!$journals_loc?.entry?.decrypt_kv) { $journals_loc.entry.decrypt_kv = {}; @@ -185,22 +196,24 @@ $effect(async () => { orig_entry_obj = { ...$lq__journal_entry_obj }; tmp_entry_obj = { ...$lq__journal_entry_obj }; if ($journals_loc?.entry?.decrypt_kv[$lq__journal_entry_obj?.journal_entry_id]) { + let decrypt_key = $lq__journal_obj.combined_passcode; + if (!tmp_entry_obj?.content && tmp_entry_obj?.content_encrypted) { console.log('TEST: Decrypting the content...'); - tmp_entry_obj.content = await ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, journal_key); + tmp_entry_obj.content = await ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, decrypt_key); tmp_entry_obj.content_md_html = handle_marked(tmp_entry_obj?.content); - orig_entry_obj.content = await ae_util.decrypt_wrapper(orig_entry_obj?.content_encrypted, journal_key); + orig_entry_obj.content = await ae_util.decrypt_wrapper(orig_entry_obj?.content_encrypted, decrypt_key); orig_entry_obj.content_md_html = handle_marked(orig_entry_obj?.content); } if (!tmp_entry_obj?.history && tmp_entry_obj?.history_encrypted) { console.log('TEST: Decrypting the history...'); - tmp_entry_obj.history = await ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, journal_key); + tmp_entry_obj.history = await ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, decrypt_key); tmp_entry_obj.history_md_html = handle_marked(tmp_entry_obj?.history); - orig_entry_obj.history = await ae_util.decrypt_wrapper(orig_entry_obj?.history_encrypted, journal_key); + orig_entry_obj.history = await ae_util.decrypt_wrapper(orig_entry_obj?.history_encrypted, decrypt_key); orig_entry_obj.history_md_html = handle_marked(orig_entry_obj?.history); } } @@ -284,20 +297,53 @@ $effect(() => { }); -$effect(async () => { - if ($journals_sess?.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified && tmp_entry_obj?.content_encrypted && !tmp_entry_obj.content) { - console.log('TEST: Decrypting the content before displaying it...'); - tmp_entry_obj.content = await ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, journal_key); - tmp_entry_obj.content_md_html = handle_marked(tmp_entry_obj?.content); - } +// Better decrypted content and history handling +$effect(() => { + if ($lq__journal_entry_obj?.content_encrypted && $journals_sess?.journal_kv[$lq__journal_obj?.journal_id]?.journal_passcode_verified && !$journals_sess?.journal_kv[$lq__journal_obj?.journal_id]?.journal_passcode_decrypted) { - if ($journals_sess?.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified && tmp_entry_obj?.history_encrypted && !tmp_entry_obj.history) { - console.log('TEST: Decrypting the history before displaying it...'); - tmp_entry_obj.history = await ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, journal_key); - tmp_entry_obj.history_md_html = handle_marked(tmp_entry_obj?.history); + if ($journals_sess.journal_kv[$lq__journal_obj?.journal_id]?.typed_journal_passcode?.length) { + journal_key = ae_util.derive_key_from_passcode($journals_sess.journal_kv[$lq__journal_obj?.journal_id]?.typed_journal_passcode); + } else { + journal_key = $lq__journal_obj?.private_passcode; + } + + if (journal_key == null) { + console.log('TEST: No journal key available to decrypt the content.'); + return; + } + + let content_decrypted = null; + + $journals_sess.journal_kv[$lq__journal_obj?.journal_id].journal_passcode_decrypted = 'processing'; + + content_decrypted = ae_util.decrypt_wrapper($lq__journal_entry_obj?.content_encrypted, journal_key); + console.log('TEST: Decrypted content:', content_decrypted); + + $journals_sess.journal_kv[$lq__journal_obj?.journal_id].journal_passcode_decrypted = true; + + // $journals_slct.journal_entry_obj.content_decrypted = content_decrypted; + tmp_entry_obj.content = content_decrypted; + tmp_entry_obj.content_md_html = handle_marked(content_decrypted); } }); + + +// // Old decrypted content and history handling +// $effect(() => { +// if ($journals_sess?.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified && tmp_entry_obj?.content_encrypted && !tmp_entry_obj.content) { +// console.log('TEST: Decrypting the content before displaying it...'); +// tmp_entry_obj.content = ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, journal_key); +// tmp_entry_obj.content_md_html = handle_marked(tmp_entry_obj?.content); +// } + +// if ($journals_sess?.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified && tmp_entry_obj?.history_encrypted && !tmp_entry_obj.history) { +// console.log('TEST: Decrypting the history before displaying it...'); +// tmp_entry_obj.history = ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, journal_key); +// tmp_entry_obj.history_md_html = handle_marked(tmp_entry_obj?.history); +// } +// }); + // const test_html = marked.parse('# Marked in Node.js\n\nRendered by **marked**.'); async function update_journal_entry() { @@ -343,47 +389,78 @@ async function update_journal_entry() { tags: tmp_entry_obj?.tags, }; - if (tmp_entry_obj?.content) { + if (tmp_entry_obj?.content || tmp_entry_obj?.content_encrypted) { + let decrypt_key = $lq__journal_obj.combined_passcode; + // If private, it needs to be (re-)encrypted. if (!tmp_entry_obj?.private) { - let { left_over_string, cut_out_string } = handle_cut_string(tmp_entry_obj?.content); + console.log('TEST: Public or non-private entry; handling cut tags if needed...'); - // let new_content_string = ''; - // let cut_content_string = ''; - // {new_content_string, cut_content_string} + // let left_over_string = ''; + // let cut_out_string = ''; - data_kv.content = left_over_string; - - if (tmp_entry_obj?.history_encrypted) { - console.log('TEST: Decrypting the history before saving it...'); - decrypted_history = await handle_decrypt_string(tmp_entry_obj?.history_encrypted, journal_key); + if (tmp_entry_obj.content) { + // left_over_string, cut_out_string = handle_cut_string(tmp_entry_obj?.content); + // data_kv.content = left_over_string; + data_kv.content = tmp_entry_obj?.content; + } else if (tmp_entry_obj.content_encrypted) { + // We need to decrypt the content first, then handle the cut tags. + let decrypted_content = await ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, decrypt_key); + data_kv.content = decrypted_content; } else { - decrypted_history = tmp_entry_obj?.history; + data_kv.content = ''; } - data_kv.history = decrypted_history ?? '' + '\n' + cut_out_string; + let { left_over_string, cut_out_string } = handle_cut_string(data_kv.content); + data_kv.content = left_over_string; + + console.log('TEST: data_kv.content:', data_kv.content); + + data_kv.content_encrypted = null; + + // if (tmp_entry_obj?.history_encrypted) { + // console.log('TEST: Decrypting the history before saving it...'); + // decrypted_history = await handle_decrypt_string(tmp_entry_obj?.history_encrypted, decrypt_key); + // } else { + // decrypted_history = tmp_entry_obj?.history; + // } + + if (cut_out_string) { + let current_timestamp = new Date().toISOString(); + cut_out_string = `## Cut on ${current_timestamp}\n` + cut_out_string; + } + + if (tmp_entry_obj?.history) { + data_kv.history = tmp_entry_obj?.history ?? '' + '\n\n' + cut_out_string; + } else { + data_kv.history = cut_out_string; + } + + console.log('TEST: data_kv.history:', data_kv.history); + data_kv.history_encrypted = null; - decrypted_history = ''; + } else if (tmp_entry_obj?.private) { let { left_over_string, cut_out_string } = handle_cut_string(tmp_entry_obj?.content); // Need to decrypt the current content and current history. Assume the history has not been decrypted yet. - let content_enc_combined_data = await ae_util.encrypt_wrapper(left_over_string, journal_key); + let content_enc_combined_data = await ae_util.encrypt_wrapper(left_over_string, decrypt_key); if (log_lvl) { console.log('TEST: Encrypted string:', content_enc_combined_data); } // return content_enc_combined_data; - // let content_enc_combined_data = await handle_encrypt_string(left_over_string, journal_key) + // let content_enc_combined_data = await handle_encrypt_string(left_over_string, decrypt_key) data_kv.content_encrypted = content_enc_combined_data; data_kv.content = null; + tmp_entry_obj.content = null; // decrypted_content = ''; if (log_lvl) { console.log('TEST: Decrypting the history before saving it...'); } - decrypted_history = await ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, journal_key); + decrypted_history = await ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, decrypt_key); if (tmp_entry_obj?.history) { data_kv.history = tmp_entry_obj?.history ?? '' + '\n' + decrypted_history + '\n' + cut_out_string; @@ -395,10 +472,11 @@ async function update_journal_entry() { if (log_lvl) { console.log('TEST: Encrypting the history before saving it...'); } - let history_enc_combined_data = await ae_util.encrypt_wrapper(data_kv.history, journal_key); + let history_enc_combined_data = await ae_util.encrypt_wrapper(data_kv.history, decrypt_key); data_kv.history_encrypted = history_enc_combined_data; data_kv.history = null; + tmp_entry_obj.history decrypted_history = ''; } } @@ -452,44 +530,6 @@ async function update_journal_entry() { // } // } - // if (tmp_entry_obj?.content && tmp_entry_obj?.private) { - // // // console.log('TEST: Saving encrypted content', tmp_entry_obj?.content); - // // content = tmp_entry_obj?.content; - // // // console.log('TEST: journal_key', journal_key); - - // // // // Encrypt the content - // // // let encrypted_base64 = await ae_util.encrypt_content(content, journal_key); - // // // encrypted_base64_string = encrypted_base64.base64; - // // // encryption_iv = encrypted_base64.iv; - // // // console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_string}`); - - // // // // Combine the IV and encrypted content - // // // const combined_data = Array.from(encryption_iv).map(byte => byte.toString(16).padStart(2, '0')).join('') + ':' + encrypted_base64_string; - - // // let combined_data = await handle_encrypt_string(content, journal_key); - - // // data_kv.content_encrypted = combined_data; - // // data_kv.content = null; - // // decrypted_content = ''; - // } else if (decrypted_content && !tmp_entry_obj?.private) { - // // console.log('TEST: Saving decrypted content', decrypted_content); - // content = decrypted_content; - - // data_kv.content = content; - // decrypted_content = ''; - // } else if (tmp_entry_obj?.content_encrypted && !tmp_entry_obj?.private) { - // console.log('TEST: Decrypting the content before saving it...'); - // decrypted_content = await handle_decrypt_string(tmp_entry_obj?.content_encrypted, journal_key); - // data_kv.content = decrypted_content; // tmp_entry_obj.content - // decrypted_content = ''; - // // return false; - // } else { - // console.log('TEST: Saving content without encryption', tmp_entry_obj?.content); - // // Clear content_encrypted again. Just in case. - // // data_kv.content_encrypted = null; - // decrypted_content = ''; - // // tmp_entry_obj.content_encrypted = null; - // } // Call API to save the content try { @@ -621,32 +661,28 @@ async function change_journal_id() { // let journal_key: string = $state( 'my-secret-key-111'); // let journal_key: string = $state($lq__journal_obj?.passcode); -let journal_key = $derived(() => { - return $lq__journal_obj?.passcode || 'temp-secret-key'; -}); +// let journal_key: string = $state($lq__journal_obj?.passcode); + // console.log('TEST: journal_key', journal_key); -let content = ''; // "This is my test content to encrypt and decrypt."; -let encrypted_base64_string: string = $state(''); -let encryption_iv: null|Uint8Array = $state(null); -let decrypted_content: string = $state(''); -let trigger_decrypt: boolean = $state(false); -let decrypted_history: string = $state(''); -$effect(() => { - if ($journals_sess.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified) { - journal_key = $lq__journal_obj?.combined_passcode; - } else if ($lq__journal_obj?.passcode) { - journal_key = $lq__journal_obj?.passcode; - } else { - 'temp-secret-key'; - } - console.log('TEST: journal_key', journal_key); - // if ($lq__journal_obj?.passcode) { - // console.log('TEST: lq__journal_obj?.passcode', $lq__journal_obj?.passcode); - // journal_key = $lq__journal_obj?.passcode; - // } -}); +// $effect(() => { +// // A journal should always at least have a general passcode that can be used. If the private code is also found, then we should use the combined value as the key. +// if ($journals_sess.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified) { +// // For private +// journal_key = $lq__journal_obj?.combined_passcode; +// } else if ($lq__journal_obj?.passcode) { +// journal_key = $lq__journal_obj?.passcode; +// } else { +// 'temp-secret-key'; +// } +// console.log('TEST: journal_key', journal_key); + +// // if ($lq__journal_obj?.passcode) { +// // console.log('TEST: lq__journal_obj?.passcode', $lq__journal_obj?.passcode); +// // journal_key = $lq__journal_obj?.passcode; +// // } +// }); // $effect(async () => { // if (tmp_entry_obj?.content_encrypted && trigger_decrypt) { @@ -756,39 +792,6 @@ async function handle_decrypt_string(encrypted_string: string, passcode: string) // return decrypted_string; } -// async function handle_encrypt_string(text_string: string, passcode: string) { -// // log_lvl = 1; -// if (log_lvl) { -// console.log('TEST: handle_encrypt_string'); -// } -// if (!text_string) { -// console.log('TEST: No text string provided'); -// return ''; -// } -// if (!passcode) { -// console.log('TEST: No journal key provided'); -// return false; -// } - -// let combined_data_2 = await ae_util.encrypt_wrapper(text_string, passcode); -// if (log_lvl) { -// console.log('TEST: Encrypted string:', combined_data_2); -// } -// return combined_data_2; - -// // Encrypt the string using the journal key -// // let encrypted_base64 = await ae_util.encrypt_content(text_string, passcode); -// // let encrypted_base64_string = encrypted_base64.base64; -// // let encryption_iv = encrypted_base64.iv; -// // console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_string}`); - -// // const combined_data = ae_util.combine_iv_and_base64(encrypted_base64_string, encryption_iv); - -// // Combine the IV and encrypted content -// // const combined_data = Array.from(encryption_iv).map(byte => byte.toString(16).padStart(2, '0')).join('') + ':' + encrypted_base64_string; - -// // return combined_data; -// } // return new_string and cut_string function handle_cut_string(old_string: string) { @@ -877,30 +880,6 @@ $effect(() => { update_journal_entry(); - - - // ae_promises.journal_entry_obj = archives_func.update_ae_obj__journal_entry({ - // api_cfg: $ae_api, - // journal_entry_id: tmp_entry_obj.journal_entry_id, - // data_kv: { - // hosted_file_id_random: slct_hosted_file_id, - // // file_path: hosted_file_obj_li[0].file_path, - // filename: slct_hosted_file_obj.filename, - // file_extension: slct_hosted_file_obj.extension, - // journal_entry_type: 'hosted_file', - // }, - // log_lvl: log_lvl - // }) - // .then(function (journal_entry_obj_update_result) { - // // tmp_entry_obj.journal_entry_obj = $lq__journal_entry_obj; - // tmp_entry_obj.journal_entry_obj = journal_entry_obj_update_result; - // }) - // .catch(function (error) { - // console.log('Something went wrong.'); - // console.log(error); - // return false; - // }); - slct_hosted_file_id = null; slct_hosted_file_obj = null; } @@ -1013,7 +992,7 @@ $effect(() => { -
+
@@ -1166,49 +1145,56 @@ $effect(() => {