Compare commits

..

No commits in common. "5dba3f8675c4d60a9231fdd9eac533dd863c9ee1" and "ab676217cdd0f8ad6f43ec4235f8fed3caffd446" have entirely different histories.

6 changed files with 41 additions and 173 deletions

View File

@ -3,14 +3,14 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>encryptme: Simple AES encryption/decryption</title>
<meta name="description" content="Easy to use and simple online tool for AES encryption and decryption. <meta name="description" content="Easy to use and simple online tool for AES encryption and decryption.
Advanced settings allow control over the IV, AES mode, and PBKDF2 parameters."> Advanced settings allow control over the IV, AES mode, and PBKDF2 parameters.">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>encryptme: Simple AES encryption/decryption</title>
<link rel="stylesheet" href="style.css">
</head> </head>
<body> <body>
<script src="scripts/header-template.js"></script> <h1>encryptme</h1>
<h1>AES</h1> <h1>AES</h1>
<script src="scripts/interface.js"></script> <script src="scripts/interface.js"></script>
<script src="scripts/aes.js"></script> <script src="scripts/aes.js"></script>

View File

@ -3,13 +3,13 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>encryptme</title>
<meta name="description" content="Easy to use and simple online tools for encryption and decryption."> <meta name="description" content="Easy to use and simple online tools for encryption and decryption.">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>encryptme</title>
<link rel="stylesheet" href="style.css">
</head> </head>
<body> <body>
<script src="scripts/header-template.js"></script> <h1>encryptme</h1>
<h2>Tools</h2> <h2>Tools</h2>
<h3>Encryption/decryption</h3> <h3>Encryption/decryption</h3>
<a href="aes.html">AES</a> <a href="aes.html">AES</a>

View File

@ -61,20 +61,6 @@ let encManualIV = encForm.createCheckBox({
label: "Use fixed IV instead of random", label: "Use fixed IV instead of random",
advanced: true 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 encButton = encForm.createButton({label: "Encrypt"});
let encOut = encForm.createOutput({ let encOut = encForm.createOutput({
label: "Output", 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( return window.crypto.subtle.deriveKey(
{ {
"name": "PBKDF2", "name": "PBKDF2",
@ -131,7 +117,7 @@ function getKey(keyMaterial, salt, pbkdf2Iters, encMode) {
}, },
keyMaterial, keyMaterial,
{ {
"name": encMode, "name": "AES-GCM",
"length": 256 "length": 256
}, },
true, 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() { encButton.handle.addEventListener("click", async function() {
let keyMaterial = await getKeyMaterial(encPass.value); let keyMaterial = await getKeyMaterial(encPass.value);
let key; let key;
@ -175,7 +140,7 @@ encButton.handle.addEventListener("click", async function() {
key = await window.crypto.subtle.importKey( key = await window.crypto.subtle.importKey(
"raw", "raw",
encKey.value, encKey.value,
{"name": encMode.value}, {"name": "AES-GCM"},
true, true,
["encrypt", "decrypt"] ["encrypt", "decrypt"]
); );
@ -187,7 +152,7 @@ encButton.handle.addEventListener("click", async function() {
encSalt.value = salt; 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); encKey.value = await window.crypto.subtle.exportKey("raw", key);
} }
@ -202,19 +167,14 @@ encButton.handle.addEventListener("click", async function() {
let enc = new TextEncoder(); let enc = new TextEncoder();
let msgEncoded = enc.encode(encMsg.value); let msgEncoded = enc.encode(encMsg.value);
let ciphertext; let ciphertext = await window.crypto.subtle.encrypt(
switch (encMode.value) { {
case "AES-GCM": "name": "AES-GCM",
ciphertext = await aesGcmEnc(key, iv, msgEncoded); "iv": iv
break; },
case "AES-CBC": key,
ciphertext = await aesCbcEnc(key, iv, msgEncoded); msgEncoded
break; );
default:
let e = Error(`Mode '${encMode.value}' is not implemented.`);
encMode.handleError(e);
return;
}
encOutRaw.value = ciphertext; encOutRaw.value = ciphertext;
@ -222,49 +182,26 @@ encButton.handle.addEventListener("click", async function() {
"ciphertext": bufToB64(ciphertext), "ciphertext": bufToB64(ciphertext),
"salt": bufToB64(salt), "salt": bufToB64(salt),
"iv": bufToB64(iv), "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() { decButton.handle.addEventListener("click", async function() {
let msgEncoded = decMsg.value; let msgEncoded = decMsg.value;
let ciphertext, iv, salt, encMode, pbkdf2Iters; let ciphertext, iv, salt, pbkdf2Iters;
try { try {
ciphertext = new b64ToBuf(msgEncoded.ciphertext); ciphertext = new b64ToBuf(msgEncoded.ciphertext);
iv = new Uint8Array(b64ToBuf(msgEncoded.iv)); iv = new Uint8Array(b64ToBuf(msgEncoded.iv));
salt = new Uint8Array(b64ToBuf(msgEncoded.salt)); salt = new Uint8Array(b64ToBuf(msgEncoded.salt));
encMode = msgEncoded.encMode;
pbkdf2Iters = msgEncoded.pbkdf2Iters; pbkdf2Iters = msgEncoded.pbkdf2Iters;
if (pbkdf2Iters < 1 || pbkdf2Iters%1 !== 0) { 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) { } else if (pbkdf2Iters > 1000000) {
decMsg.alertBox("alert-info", `PBKDF2 is using ${pbkdf2Iters} iterations: this might take a long time...`); decMsg.alertBox("alert-info", `PBKDF2 is using ${pbkdf2Iters} iterations: this might take a long time...`);
} }
} catch (e) { } catch (e) {
decMsg.handleError(e, "Invalid encrypted payload."); decMsg.alertBox("alert-error", "Invalid encrypted payload.");
} }
if (ciphertext === undefined if (ciphertext === undefined
@ -278,40 +215,30 @@ decButton.handle.addEventListener("click", async function() {
let keyMaterial = await getKeyMaterial(decPass.value); let keyMaterial = await getKeyMaterial(decPass.value);
let key; let key;
if (decManualKey.value) { if (decManualKey.value) {
try { key = await window.crypto.subtle.importKey(
key = await window.crypto.subtle.importKey( "raw",
"raw", decKey.value,
decKey.value, {"name": "AES-GCM"},
{"name": encMode}, true,
true, ["encrypt", "decrypt"]
["encrypt", "decrypt"] );
);
} catch (e) {
decMsg.handleError(e);
}
} else { } else {
key = await getKey(keyMaterial, salt, pbkdf2Iters, encMode); key = await getKey(keyMaterial, salt, pbkdf2Iters);
} }
let plaintext; let plaintext;
try { try {
switch (encMode) { plaintext = await window.crypto.subtle.decrypt(
case "AES-GCM": {
plaintext = await aesGcmDec(key, iv, ciphertext); "name": "AES-GCM",
break; "iv": iv
case "AES-CBC": },
plaintext = await aesCbcDec(key, iv, ciphertext); key,
break; ciphertext
default: );
throw Error(`Mode '${encMode.value}' is not implemented.`);
}
} catch (e) { } catch (e) {
if (e.message !== "" && e.message !== undefined) { decPass.alertBox("alert-error", "Decryption error: incorrect password?");
decMsg.handleError(e, "Error during decryption.");
} else {
decMsg.handleError(Error("Could not decrypt; is your password/key correct?"));
}
} }
let dec = new TextDecoder(); let dec = new TextDecoder();

View File

@ -1,8 +0,0 @@
header = document.createElement("div");
header.classList.add("page-header");
header.innerHTML = `
<a href="index.html"><h1>encryptme</h1></a>
`
document.body.appendChild(header);

View File

@ -194,36 +194,6 @@ class Form extends InterfaceElement {
return this.appendElement(new FormElement(params)); 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) { createTextArea(params) {
params.tag = document.createElement("textarea"); params.tag = document.createElement("textarea");
dataTypeSupports(params, ["plaintext", "b64", "json-b64"]); dataTypeSupports(params, ["plaintext", "b64", "json-b64"]);
@ -346,8 +316,6 @@ class FormElement extends InterfaceElement {
} }
case "bool": case "bool":
return this.handle.checked; return this.handle.checked;
case "category":
return this.handle.value;
case "none": case "none":
return undefined; return undefined;
} }
@ -367,9 +335,6 @@ class FormElement extends InterfaceElement {
case "bool": case "bool":
this.handle.checked = x; this.handle.checked = x;
break; break;
case "category":
this.handle.value = x;
break;
} }
} }
@ -413,13 +378,6 @@ class FormElement extends InterfaceElement {
this.handle.after(box); this.handle.after(box);
this.alerts.push(box); this.alerts.push(box);
} }
handleError(e, extraInfo="") {
if (extraInfo !== "") {
extraInfo = ` (${extraInfo})`;
}
this.alertBox("alert-error", e.message + extraInfo);
console.error(e);
}
clearAlerts() { clearAlerts() {
for (const box of this.alerts) { for (const box of this.alerts) {
box.remove(); box.remove();

View File

@ -127,11 +127,6 @@ button:active {
background: #0077ff44; background: #0077ff44;
} }
.page-header a {
color: #000000;
text-decoration: none;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
body { body {
color: #c9d1d9; color: #c9d1d9;
@ -154,10 +149,6 @@ button:active {
background: #1d2127; background: #1d2127;
color: #c9d1d9; color: #c9d1d9;
} }
.page-header a {
color: #c9d1d9;
}
} }
[hidden] { [hidden] {