Compare commits
No commits in common. "0e0ac98c84058e1e4b72b29582b3cccfab1e0d2b" and "ab676217cdd0f8ad6f43ec4235f8fed3caffd446" have entirely different histories.
0e0ac98c84
...
ab676217cd
139
scripts/aes.js
139
scripts/aes.js
@ -61,20 +61,6 @@ let encManualIV = encForm.createCheckBox({
|
||||
label: "Use fixed IV instead of random",
|
||||
advanced: true
|
||||
});
|
||||
let encMode = encForm.createDropDown({
|
||||
label: "AES mode",
|
||||
advanced: true,
|
||||
options: [
|
||||
{
|
||||
name: "AES-GCM (Galois/Counter Mode)",
|
||||
value: "AES-GCM"
|
||||
},
|
||||
{
|
||||
name: "AES-CBC (Cipher Block Chaining)",
|
||||
value: "AES-CBC"
|
||||
},
|
||||
]
|
||||
});
|
||||
let encButton = encForm.createButton({label: "Encrypt"});
|
||||
let encOut = encForm.createOutput({
|
||||
label: "Output",
|
||||
@ -121,7 +107,7 @@ function getKeyMaterial(password) {
|
||||
);
|
||||
}
|
||||
|
||||
function getKey(keyMaterial, salt, pbkdf2Iters, encMode) {
|
||||
function getKey(keyMaterial, salt, pbkdf2Iters) {
|
||||
return window.crypto.subtle.deriveKey(
|
||||
{
|
||||
"name": "PBKDF2",
|
||||
@ -131,7 +117,7 @@ function getKey(keyMaterial, salt, pbkdf2Iters, encMode) {
|
||||
},
|
||||
keyMaterial,
|
||||
{
|
||||
"name": encMode,
|
||||
"name": "AES-GCM",
|
||||
"length": 256
|
||||
},
|
||||
true,
|
||||
@ -139,27 +125,6 @@ function getKey(keyMaterial, salt, pbkdf2Iters, encMode) {
|
||||
);
|
||||
}
|
||||
|
||||
async function aesGcmEnc(key, iv, msgEncoded) {
|
||||
return window.crypto.subtle.encrypt(
|
||||
{
|
||||
"name": "AES-GCM",
|
||||
"iv": iv
|
||||
},
|
||||
key,
|
||||
msgEncoded
|
||||
);
|
||||
}
|
||||
async function aesCbcEnc(key, iv, msgEncoded) {
|
||||
return window.crypto.subtle.encrypt(
|
||||
{
|
||||
"name": "AES-CBC",
|
||||
"iv": iv
|
||||
},
|
||||
key,
|
||||
msgEncoded
|
||||
);
|
||||
}
|
||||
|
||||
encButton.handle.addEventListener("click", async function() {
|
||||
let keyMaterial = await getKeyMaterial(encPass.value);
|
||||
let key;
|
||||
@ -175,7 +140,7 @@ encButton.handle.addEventListener("click", async function() {
|
||||
key = await window.crypto.subtle.importKey(
|
||||
"raw",
|
||||
encKey.value,
|
||||
{"name": encMode.value},
|
||||
{"name": "AES-GCM"},
|
||||
true,
|
||||
["encrypt", "decrypt"]
|
||||
);
|
||||
@ -187,7 +152,7 @@ encButton.handle.addEventListener("click", async function() {
|
||||
encSalt.value = salt;
|
||||
}
|
||||
|
||||
key = await getKey(keyMaterial, salt, pbkdf2Iters, encMode.value);
|
||||
key = await getKey(keyMaterial, salt, pbkdf2Iters);
|
||||
encKey.value = await window.crypto.subtle.exportKey("raw", key);
|
||||
}
|
||||
|
||||
@ -202,19 +167,14 @@ encButton.handle.addEventListener("click", async function() {
|
||||
let enc = new TextEncoder();
|
||||
let msgEncoded = enc.encode(encMsg.value);
|
||||
|
||||
let ciphertext;
|
||||
switch (encMode.value) {
|
||||
case "AES-GCM":
|
||||
ciphertext = await aesGcmEnc(key, iv, msgEncoded);
|
||||
break;
|
||||
case "AES-CBC":
|
||||
ciphertext = await aesCbcEnc(key, iv, msgEncoded);
|
||||
break;
|
||||
default:
|
||||
let e = Error(`Mode '${encMode.value}' is not implemented.`);
|
||||
encMode.handleError(e);
|
||||
return;
|
||||
}
|
||||
let ciphertext = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
"name": "AES-GCM",
|
||||
"iv": iv
|
||||
},
|
||||
key,
|
||||
msgEncoded
|
||||
);
|
||||
|
||||
encOutRaw.value = ciphertext;
|
||||
|
||||
@ -222,49 +182,26 @@ encButton.handle.addEventListener("click", async function() {
|
||||
"ciphertext": bufToB64(ciphertext),
|
||||
"salt": bufToB64(salt),
|
||||
"iv": bufToB64(iv),
|
||||
"encMode": encMode.value,
|
||||
"pbkdf2Iters": pbkdf2Iters,
|
||||
"pbkdf2Iters": pbkdf2Iters
|
||||
}
|
||||
});
|
||||
|
||||
async function aesGcmDec(key, iv, ciphertext) {
|
||||
return window.crypto.subtle.decrypt(
|
||||
{
|
||||
"name": "AES-GCM",
|
||||
"iv": iv
|
||||
},
|
||||
key,
|
||||
ciphertext
|
||||
);
|
||||
}
|
||||
async function aesCbcDec(key, iv, ciphertext) {
|
||||
return window.crypto.subtle.decrypt(
|
||||
{
|
||||
"name": "AES-CBC",
|
||||
"iv": iv
|
||||
},
|
||||
key,
|
||||
ciphertext
|
||||
);
|
||||
}
|
||||
|
||||
decButton.handle.addEventListener("click", async function() {
|
||||
let msgEncoded = decMsg.value;
|
||||
|
||||
let ciphertext, iv, salt, encMode, pbkdf2Iters;
|
||||
let ciphertext, iv, salt, pbkdf2Iters;
|
||||
try {
|
||||
ciphertext = new b64ToBuf(msgEncoded.ciphertext);
|
||||
iv = new Uint8Array(b64ToBuf(msgEncoded.iv));
|
||||
salt = new Uint8Array(b64ToBuf(msgEncoded.salt));
|
||||
encMode = msgEncoded.encMode;
|
||||
pbkdf2Iters = msgEncoded.pbkdf2Iters;
|
||||
if (pbkdf2Iters < 1 || pbkdf2Iters%1 !== 0) {
|
||||
throw Error(`Invalid PBKDF2 iterations setting: ${pbkdf2Iters}`);
|
||||
decMsg.alertBox("alert-error", "Invalid PBKDF2 iters setting.");
|
||||
} else if (pbkdf2Iters > 1000000) {
|
||||
decMsg.alertBox("alert-info", `PBKDF2 is using ${pbkdf2Iters} iterations: this might take a long time...`);
|
||||
}
|
||||
} catch (e) {
|
||||
decMsg.handleError(e, "Invalid encrypted payload.");
|
||||
decMsg.alertBox("alert-error", "Invalid encrypted payload.");
|
||||
}
|
||||
|
||||
if (ciphertext === undefined
|
||||
@ -278,40 +215,30 @@ decButton.handle.addEventListener("click", async function() {
|
||||
let keyMaterial = await getKeyMaterial(decPass.value);
|
||||
let key;
|
||||
if (decManualKey.value) {
|
||||
try {
|
||||
key = await window.crypto.subtle.importKey(
|
||||
"raw",
|
||||
decKey.value,
|
||||
{"name": encMode},
|
||||
true,
|
||||
["encrypt", "decrypt"]
|
||||
);
|
||||
} catch (e) {
|
||||
decMsg.handleError(e);
|
||||
}
|
||||
key = await window.crypto.subtle.importKey(
|
||||
"raw",
|
||||
decKey.value,
|
||||
{"name": "AES-GCM"},
|
||||
true,
|
||||
["encrypt", "decrypt"]
|
||||
);
|
||||
} else {
|
||||
key = await getKey(keyMaterial, salt, pbkdf2Iters, encMode);
|
||||
key = await getKey(keyMaterial, salt, pbkdf2Iters);
|
||||
}
|
||||
|
||||
let plaintext;
|
||||
|
||||
try {
|
||||
switch (encMode) {
|
||||
case "AES-GCM":
|
||||
plaintext = await aesGcmDec(key, iv, ciphertext);
|
||||
break;
|
||||
case "AES-CBC":
|
||||
plaintext = await aesCbcDec(key, iv, ciphertext);
|
||||
break;
|
||||
default:
|
||||
throw Error(`Mode '${encMode.value}' is not implemented.`);
|
||||
}
|
||||
plaintext = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
"name": "AES-GCM",
|
||||
"iv": iv
|
||||
},
|
||||
key,
|
||||
ciphertext
|
||||
);
|
||||
} catch (e) {
|
||||
if (e.message !== "" && e.message !== undefined) {
|
||||
decMsg.handleError(e, "Error during decryption.");
|
||||
} else {
|
||||
decMsg.handleError(Error("Could not decrypt; is your password/key correct?"));
|
||||
}
|
||||
decPass.alertBox("alert-error", "Decryption error: incorrect password?");
|
||||
}
|
||||
|
||||
let dec = new TextDecoder();
|
||||
|
@ -194,36 +194,6 @@ class Form extends InterfaceElement {
|
||||
return this.appendElement(new FormElement(params));
|
||||
}
|
||||
|
||||
createDropDown(params) {
|
||||
// example for params.options:
|
||||
/*
|
||||
[
|
||||
{
|
||||
value: "volvo"
|
||||
name: "Volvo"
|
||||
},
|
||||
{
|
||||
value: "benz"
|
||||
name: "Mercedes Benz"
|
||||
}
|
||||
]
|
||||
*/
|
||||
params.fragment = new DocumentFragment();
|
||||
params.tag = document.createElement("select");
|
||||
params.labelTag = document.createElement("label");
|
||||
params.labelTag.appendChild(document.createTextNode(params.label));
|
||||
params.fragment.appendChild(params.labelTag);
|
||||
params.fragment.appendChild(params.tag);
|
||||
dataTypeSupports(params, ["category"]);
|
||||
for (const option of params.options) {
|
||||
let optTag = document.createElement("option");
|
||||
optTag.value = option.value;
|
||||
optTag.appendChild(document.createTextNode(option.name));
|
||||
params.tag.appendChild(optTag);
|
||||
}
|
||||
return this.appendElement(new FormElement(params));
|
||||
}
|
||||
|
||||
createTextArea(params) {
|
||||
params.tag = document.createElement("textarea");
|
||||
dataTypeSupports(params, ["plaintext", "b64", "json-b64"]);
|
||||
@ -346,8 +316,6 @@ class FormElement extends InterfaceElement {
|
||||
}
|
||||
case "bool":
|
||||
return this.handle.checked;
|
||||
case "category":
|
||||
return this.handle.value;
|
||||
case "none":
|
||||
return undefined;
|
||||
}
|
||||
@ -367,9 +335,6 @@ class FormElement extends InterfaceElement {
|
||||
case "bool":
|
||||
this.handle.checked = x;
|
||||
break;
|
||||
case "category":
|
||||
this.handle.value = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,13 +378,6 @@ class FormElement extends InterfaceElement {
|
||||
this.handle.after(box);
|
||||
this.alerts.push(box);
|
||||
}
|
||||
handleError(e, extraInfo="") {
|
||||
if (extraInfo !== "") {
|
||||
extraInfo = ` (${extraInfo})`;
|
||||
}
|
||||
this.alertBox("alert-error", e.message + extraInfo);
|
||||
console.error(e);
|
||||
}
|
||||
clearAlerts() {
|
||||
for (const box of this.alerts) {
|
||||
box.remove();
|
||||
|
Loading…
x
Reference in New Issue
Block a user