From f49f072fabbe1b54b91a69406ca332c2b745f1b4 Mon Sep 17 00:00:00 2001 From: dogeystamp Date: Tue, 3 Jan 2023 20:44:47 -0500 Subject: [PATCH] added manual salt, IV and key options --- scripts/aes.js | 83 ++++++++++++++++++++++++++++++++------------ scripts/interface.js | 38 +++++++++++++------- 2 files changed, 86 insertions(+), 35 deletions(-) diff --git a/scripts/aes.js b/scripts/aes.js index eaa0e22..bf23f02 100644 --- a/scripts/aes.js +++ b/scripts/aes.js @@ -1,22 +1,41 @@ let encForm = new Form({label: "Encryption"}); let encMsg = encForm.createTextArea({label: "Message"}); -let encPass = encForm.createPasswordInput({label: "Password"}); -let encManualMode = encForm.createCheckBox({ - label: "Manual mode", - advanced: true +let encPass = encForm.createPasswordInput({ + label: "Password", + enabledFunc: function() {return !encManualKey.value} }); -let encSalt = encForm.createTextBox({ +let encSalt = encForm.createMediumTextBox({ label: "PBKDF2 salt", dataType: "b64", advanced: true, - disabled: true + enabled: false, + enabledFunc: function() {return encManualSalt.value && !encManualKey.value} }); -let encIV = encForm.createTextBox({ +let encManualSalt = encForm.createCheckBox({ + label: "Use fixed salt instead of random", + advanced: true +}); +let encKey = encForm.createMediumTextBox({ + label: "Key", + dataType: "b64", + advanced: true, + enabled: false, + enabledFunc: function() {return encManualKey.value} +}); +let encManualKey = encForm.createCheckBox({ + label: "Use fixed key instead of password", + advanced: true +}); +let encIV = encForm.createMediumTextBox({ label: "IV", dataType: "b64", advanced: true, - disabled: true + enabledFunc: function() {return encManualIV.value} +}); +let encManualIV = encForm.createCheckBox({ + label: "Use fixed IV instead of random", + advanced: true }); let encButton = encForm.createButton({label: "Encrypt"}); let encOut = encForm.createOutput({ @@ -39,7 +58,6 @@ let decPass = decForm.createPasswordInput({label: "Password"}); let decButton = decForm.createButton({label: "Decrypt"}); let decOut = decForm.createOutput({label: "Output"}); - function getKeyMaterial(password) { let enc = new TextEncoder(); return window.crypto.subtle.importKey( @@ -69,14 +87,38 @@ function getKey(keyMaterial, salt) { ); } -async function encrypt() { - let keyMaterial = await getKeyMaterial(encPass.value); - let salt = window.crypto.getRandomValues(new Uint8Array(16)); - encSalt.value = salt; - let key = await getKey(keyMaterial, salt); +encButton.handle.addEventListener("click", async function() { - let iv = window.crypto.getRandomValues(new Uint8Array(16)); - encIV.value = iv; + let salt; + if (encSalt.enabledFunc()) { + salt = encSalt.value; + } else { + salt = window.crypto.getRandomValues(new Uint8Array(16)); + encSalt.value = salt; + } + + let keyMaterial = await getKeyMaterial(encPass.value); + let key; + if (encManualKey.value) { + key = await window.crypto.subtle.importKey( + "raw", + encKey.value, + {"name": "AES-GCM"}, + true, + ["encrypt", "decrypt"] + ); + } else { + key = await getKey(keyMaterial, salt); + encKey.value = await window.crypto.subtle.exportKey("raw", key); + } + + let iv; + if (encManualIV.value) { + iv = encIV.value; + } else { + iv = window.crypto.getRandomValues(new Uint8Array(16)); + encIV.value = iv; + } let enc = new TextEncoder(); let msgEncoded = enc.encode(encMsg.value); @@ -97,9 +139,9 @@ async function encrypt() { "salt": bufToB64(salt), "iv": bufToB64(iv) } -} +}); -async function decrypt() { +decButton.handle.addEventListener("click", async function() { let msgEncoded = decMsg.value; let ciphertext, iv, salt; @@ -135,7 +177,4 @@ async function decrypt() { let dec = new TextDecoder(); decOut.value = `${dec.decode(plaintext)}`; -} - -encButton.handle.addEventListener("click", encrypt); -decButton.handle.addEventListener("click", decrypt); +}); diff --git a/scripts/interface.js b/scripts/interface.js index ef3661b..cf1c15a 100644 --- a/scripts/interface.js +++ b/scripts/interface.js @@ -1,12 +1,18 @@ class InterfaceElement { rootNodes = []; - constructor({fragment}) { + constructor({fragment, enabledFunc}) { if (fragment === undefined) { this.fragment = new DocumentFragment(); } else { this.fragment = fragment; } + + if (enabledFunc === undefined) { + this.enabledFunc = function(){ return true; }; + } else { + this.enabledFunc = enabledFunc; + } } scanNodes() { @@ -34,6 +40,15 @@ class InterfaceElement { if (this.hidden === true) this.clearAlerts(); } + + #enabled = true; + get enabled() { + return this.#enabled; + } + set enabled(x) { + this.#enabled = x; + this.handle.disabled = !this.#enabled; + } } function dataTypeSupports(params, validTypes) { @@ -59,6 +74,7 @@ class Form extends InterfaceElement { let labelTag = document.createElement("h2"); labelTag.appendChild(document.createTextNode(label)); this.fragment.appendChild(labelTag); + this.rootNodes.push(labelTag); } this.fragment.appendChild(this.handle); @@ -100,6 +116,7 @@ class Form extends InterfaceElement { appendElement(elem) { elem.mount(this.handle); this.elements.push(elem); + this.rootNodes.push(...elem.rootNodes); if (elem.advanced) { elem.hidden = !this.advanced; } @@ -154,6 +171,11 @@ class Form extends InterfaceElement { li.appendChild(params.tag); li.appendChild(params.labelTag); dataTypeSupports(params, ["bool"]); + params.tag.addEventListener("change", function() { + for (const elem of this.elements) { + elem.enabled = elem.enabledFunc(); + } + }.bind(this)); return this.appendElement(new FormElement(params)); } @@ -185,17 +207,8 @@ function bufToB64 (buf) { } class FormElement extends InterfaceElement { - #enabled = true; - get enabled() { - return this.#enabled; - } - set enabled(x) { - this.#enabled = x; - this.handle.disabled = !this.#enabled; - } - - constructor({tag, labelTag, label="", fragment, dataType, advanced=false, enabled=true}) { - super({fragment}); + constructor({tag, labelTag, label="", fragment, dataType, advanced=false, enabled=true, enabledFunc}) { + super({fragment, enabled, enabledFunc}); this.labelText = label; if (labelTag === undefined) { @@ -211,7 +224,6 @@ class FormElement extends InterfaceElement { this.handle = tag; this.dataType = dataType; - this.enabled = enabled; this.advanced = advanced; if (this.advanced === true) this.hidden = true;