Wrapping up for the night. Lots of work on encryption related.

This commit is contained in:
Scott Idem
2025-09-10 20:58:10 -04:00
parent cc6186467a
commit 084e52be15
3 changed files with 171 additions and 184 deletions

View File

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

View File

@@ -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 ?? {} ) };

View File

@@ -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<ArrayBuffer> = $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<ArrayBuffer> = $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(() => {
</h2>
</div>
<div class="grow flex flex-row flex-wrap gap-2 items-center justify-end">
<div class="flex flex-row flex-wrap gap-2 items-center justify-end">
<div class="flex flex-row flex-wrap gap-1 items-center justify-end">
<!-- Tags for journal entry. Comma delimited list. -->
@@ -1166,49 +1145,56 @@ $effect(() => {
<button
type="button"
onclick={async () => {
if (tmp_entry_obj?.private && decrypted_content) {
decrypted_content = '';
// tmp_entry_obj.content = null;
} else if (tmp_entry_obj?.private && tmp_entry_obj?.content_encrypted) {
if (!$journals_loc?.entry?.decrypt_kv[$lq__journal_entry_obj?.journal_entry_id]) {
if (confirm('Are you sure you want to decrypt the content to view/edit?')) {
$journals_loc.entry.decrypt_kv[$lq__journal_entry_obj?.journal_entry_id] = true;
$journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id] = 'current';
console.log(tmp_entry_obj?.private);
console.log($lq__journal_obj?.combined_passcode);
console.log(tmp_entry_obj?.content_encrypted);
if (tmp_entry_obj?.private
&& $lq__journal_obj?.combined_passcode
&& tmp_entry_obj?.content_encrypted) {
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_md_html = handle_marked(tmp_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_md_html = handle_marked(tmp_entry_obj?.history);
}
// trigger_decrypt = true;
// handle_decrypt_content();
// handle_decrypt_string(tmp_entry_obj?.content_encrypted, journal_key).then((result) => {
// decrypted_content = result;
// console.log('TEST: Decrypted content:', decrypted_content);
// });
// decrypted_content = await ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, journal_key);
if (!tmp_entry_obj?.content) {
console.log(`TEST: key = ${$lq__journal_obj.passcode}:${$lq__journal_obj.private_passcode} OR ${$lq__journal_obj.combined_passcode} OR ${journal_key}`);
// // decrypted_content = await handle_decrypt_string(tmp_entry_obj?.content_encrypted, journal_key);
// tmp_entry_obj.content = decrypted_content;
// console.log('TEST: Decrypted content:', decrypted_content);
} else {
return false;
}
// let decrypt_key = 'temp-secret-key';
// let decrypt_key = 'sti-journals-2025:centauri';
let decrypt_key = $lq__journal_obj?.combined_passcode;
// let decrypt_key = `${$lq__journal_obj.passcode}:`;
// let decrypt_key = `${$lq__journal_obj.private_passcode}`;
console.log(`TEST: Decrypting the content... ${$lq__journal_obj?.combined_passcode}`);
// WARNING: await is important here
tmp_entry_obj.content = await ae_util.decrypt_wrapper(tmp_entry_obj?.content_encrypted, $lq__journal_obj?.combined_passcode);
console.log('TEST: Content Markdown render to HTML:', tmp_entry_obj?.content);
tmp_entry_obj.content_md_html = await handle_marked(tmp_entry_obj?.content);
console.log(`TEST: Decrypting the history... ${$lq__journal_obj?.combined_passcode}`);
// WARNING: await is important here
tmp_entry_obj.history = await ae_util.decrypt_wrapper(tmp_entry_obj?.history_encrypted, $lq__journal_obj?.combined_passcode);
console.log('TEST: History Markdown render to HTML:', tmp_entry_obj?.history);
tmp_entry_obj.history_md_html = await handle_marked(tmp_entry_obj?.history);
// TO DO: Use this to toggle and trigger the decryption of the content/history :TO DO
$journals_sess.entry.decrypt_kv[$lq__journal_entry_obj?.journal_entry_id] = true;
// TO DO: Use this to toggle and trigger the decryption of the content/history :TO DO
} else {
$journals_loc.entry.decrypt_kv[$lq__journal_entry_obj?.journal_entry_id] = false;
$journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id] = false;
console.log(`TEST: Not decrypting the content...`);
// Clear out the decrypted content and history to prevent it from being seen.
tmp_entry_obj.content = null;
tmp_entry_obj.content_md_html = null;
tmp_entry_obj.history = null;
tmp_entry_obj.history_md_html = null;
// TO DO: Use this to toggle and trigger the clearing of the decrypted content/history :TO DO
$journals_sess.entry.decrypt_kv[$lq__journal_entry_obj?.journal_entry_id] = false;
// TO DO: Use this to toggle and trigger the clearing of the decrypted content/history :TO DO
}
}
console.log('TEST: tmp_entry_obj:', tmp_entry_obj);
}}
class:hidden={!$lq__journal_entry_obj?.private || !tmp_entry_obj?.content_encrypted}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle viewing/editing of private encrypted content"