From 48e562c9363320a82b606cd3e3c4ee61ca7be557 Mon Sep 17 00:00:00 2001 From: dogeystamp Date: Wed, 28 Dec 2022 19:04:46 -0500 Subject: [PATCH] Initial prototype --- dec.html | 23 ++++++++++ enc.html | 23 ++++++++++ encryption.js | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 82 +++++++++++++++++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 dec.html create mode 100644 enc.html create mode 100644 encryption.js create mode 100644 style.css diff --git a/dec.html b/dec.html new file mode 100644 index 0000000..7735567 --- /dev/null +++ b/dec.html @@ -0,0 +1,23 @@ + + + + + + + encryptme: Decryption + + + + +

encryptme

+ + + + + + + + + diff --git a/enc.html b/enc.html new file mode 100644 index 0000000..ba0dea6 --- /dev/null +++ b/enc.html @@ -0,0 +1,23 @@ + + + + + + + encryptme: Encryption + + + + +

encryptme

+ + + + + + + + + diff --git a/encryption.js b/encryption.js new file mode 100644 index 0000000..04f742a --- /dev/null +++ b/encryption.js @@ -0,0 +1,125 @@ +function getMsg() { + return msg = document.getElementById("msg").value; +} + +function getMsgEncoding () { + let enc = new TextEncoder(); + return enc.encode(getMsg()); +} + +function getKeyMaterial () { + let pass = document.getElementById("password"); + let enc = new TextEncoder(); + return window.crypto.subtle.importKey( + "raw", + enc.encode(pass), + "PBKDF2", + false, + ["deriveKey"] + ); +} + +function getKey (keyMaterial, salt) { + return window.crypto.subtle.deriveKey( + { + "name": "PBKDF2", + "hash": "SHA-256", + "salt": salt, + "iterations": 300000 + }, + keyMaterial, + { + "name": "AES-GCM", + "length": 256 + }, + true, + ["encrypt", "decrypt"] + ); +} + +function bufTo64 (buf) { + let bytes = new Uint8Array(buf); + let ascii = '' + for (var i = 0; i < bytes.byteLength; i++) { + ascii += String.fromCharCode(bytes[i]); + } + return btoa(ascii); +} + +function b64ToBuf (b64) { + let ascii = atob(b64); + let buf = new ArrayBuffer(ascii.length); + let bytes = new Uint8Array(buf); + for (var i = 0; i < ascii.length; i++) { + bytes[i] = ascii.charCodeAt(i); + } + return buf; +} + +function concatBuf(buf1, buf2) { + let tmp = new Uint8Array(buf1.byteLength + buf2.byteLength); + tmp.set(new Uint8Array(buf1), 0); + tmp.set(new Uint8Array(buf2), buf1.byteLength); + return tmp.buffer; +} + +async function exportKey (key) { + let k = await window.crypto.subtle.exportKey("raw", key); + return bufTo64(k); +} + +async function enc () { + outBox = document.getElementById("ciphertext"); + outBox.innerHTML = ''; + + let keyMaterial = await getKeyMaterial(); + let salt = window.crypto.getRandomValues(new Uint8Array(16)); + let key = await getKey(keyMaterial, salt); + let iv = window.crypto.getRandomValues(new Uint8Array(16)); + let msgEncoded = getMsgEncoding(); + + ciphertext = await window.crypto.subtle.encrypt( + { + "name": "AES-GCM", + "iv": iv + }, + key, + msgEncoded + ); + + let output = concatBuf(concatBuf(ciphertext, salt), iv); + + outBox.innerHTML = `${bufTo64(output)}`; + let keyExp = await exportKey (key); + window.alert(bufTo64(iv)); +} + +async function dec () { + outBox = document.getElementById("plaintext"); + outBox.innerHTML = ''; + + let msgEncoded = b64ToBuf(getMsg()); + + let ciphertext = new Uint8Array(msgEncoded.slice(0, -32)); + let iv = new Uint8Array(msgEncoded.slice(-16)); + let salt = new Uint8Array(msgEncoded.slice(-32, -16)); + + let keyMaterial = await getKeyMaterial(); + let key = await getKey(keyMaterial, salt); + + try { + let plaintext = await window.crypto.subtle.decrypt( + { + "name": "AES-GCM", + "iv": iv + }, + key, + ciphertext + ); + + let dec = new TextDecoder(); + outBox.innerHTML = `${dec.decode(plaintext)}`; + } catch (e) { + window.alert(e.name); + } +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..1a338aa --- /dev/null +++ b/style.css @@ -0,0 +1,82 @@ +body { + max-width: 650px; + margin: 40px auto; + padding: 0 10px; + color: #444444; + background: #eeeeee; +} + +h1, h2, h3, h4, h5, h6 { + color: #666666; +} + +body, button { + font: 18px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} + + +textarea { + width: 100%; + height: 15em; + padding-top: 1em; + resize: none; +} + +label, input, button, textarea { + display: block; + margin-top: 1em; + border: none; + border-radius: 5px; + transition-duration: 0.2s; +} + +input, textarea, button { + border: 1px solid #44444444; +} + +input:focus, textarea:focus, button:focus { + outline: none; +} + +input:focus, textarea:focus { + border: 1px solid #444444aa; +} + +p { + text-align: justify; +} + +button { + transition-duration: 0.05s; + border: 1px solid #44444444; +} +button:hover { + border: 1px solid #444444aa; +} +button:active { + opacity: 50%; +} + +@media (prefers-color-scheme: dark) { + body { + color: #c9d1d9; + background: #0d1117; + } + + h1, h2, h3, h4, h5, h6 { + color: #c9d1d9; + } + + a:link { + color: #58a6ff; + } + + a:visited { + color: #8e96f0; + } + + textarea, input, button { + background: #1d2127; + color: #c9d1d9; + } +}