From encrypt/decrypt functions built around crypto.subtle.encrypt/decrypt, here is a summary solution.
The function to encrypt forms:
async function encryptedSubmitForm(formName) {
form = document.forms[formName];
form_types = [];
for (idx=0; idx < form.elements.length; idx += 1) {
dtype = form.elements[idx].type
form_types.push(dtype)
form.elements[idx].type = "text"
form.elements[idx].value = await encrypt(form.elements[idx].value, ekey());
await sleep(8);
}
form.submit();
for (idx=0; idx < form.elements.length; idx += 1) {
await sleep(8);
form.elements[idx].type = form_types[idx];
form.elements[idx].value = await decrypt(form.elements[idx].value, ekey());
}
}
The form "submit" button does the submit explicitly from js:
<input type="button" onclick="encryptedSubmitForm('new')" value="+">
The form data types don't have to be flipped, I'm still considering using fetch directly, but it gives a nice visual clarity of what's going on to see it in action. If you don't flip the form data types, the data gets dropped.
On the decryption side of the story, I've got tables with fields like this
followed with a page script to call decryptElements():
<td class="encrypted">{{prow.datebin}}</td>
...
<script>
decryptElements();
</script>
And lastly here is the e2ee decryption:
async function decryptElements() {
cts = document.getElementsByClassName("encrypted");
for (ct of cts) {
await sleep(16)
ct.textContent = await decrypt(ct.textContent, ekey());
}
}
Security concerns run amok, this presumes SSL, and is in addition to server side encryption, not as an alternative. Cross origin local storage leakage could happen. Omit or pin any external dependency with integrity checks:
<script src="https://cdnjs.cloudflare.com/ajax/libs/bitcoinjs-lib/0.2.0-1/bitcoinjs-min.js" integrity="sha256-FilB5ir32toR4c80H4e31Wzh7MbA0kOd/LzvRxgletA=" crossorigin="anonymous"></script>