From 31f5736c447f5edd6b918edce5f10564d20370f3 Mon Sep 17 00:00:00 2001 From: molecula451 Date: Thu, 29 Feb 2024 23:59:19 -0400 Subject: [PATCH] chore: initial commit keygen app --- package.json | 3 +- static/key-generator/keygen.ts | 134 +++++++++++++++++++++++++++++++++ yarn.lock | 12 +++ 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 static/key-generator/keygen.ts diff --git a/package.json b/package.json index 73e995c..2f41a08 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "open-source" ], "dependencies": { - "dotenv": "^16.4.4" + "dotenv": "^16.4.4", + "libsodium-wrappers": "^0.7.13" }, "devDependencies": { "@commitlint/cli": "^18.6.1", diff --git a/static/key-generator/keygen.ts b/static/key-generator/keygen.ts new file mode 100644 index 0000000..6853de7 --- /dev/null +++ b/static/key-generator/keygen.ts @@ -0,0 +1,134 @@ +import _sodium from "libsodium-wrappers"; + +const classes = ["error", "warning", "success"]; +const CYPHER_KEY = "#cipherKey"; + +function statusToggle(target: "error" | "warning" | "success", value: string) { + const statusKey = document.querySelector("#statusKey") as HTMLInputElement; + + classes.forEach((e) => { + if (e !== target) { + statusKey.classList.remove(e); + } + }); + statusKey.classList.add(target); + statusKey.value = value; +} + +async function sodiumKeyBox() { + const privKey = document.querySelector("#privKey") as HTMLInputElement; + const pubKey = document.querySelector("#pubKey") as HTMLInputElement; + const cipherKey = document.querySelector(CYPHER_KEY) as HTMLInputElement; + cipherKey.value = ""; + try { + await _sodium.ready; + const sodium = _sodium; + + const { privateKey, publicKey } = sodium.crypto_box_keypair("base64"); + privKey.value = privateKey; + pubKey.value = publicKey; + statusToggle("success", `Success: Key Generation is ok.`); + } catch (error: unknown) { + if (error instanceof Error) { + statusToggle("error", `Error: ${error.message}`); + } else { + statusToggle("error", `Error: ${JSON.stringify(error)}`); + } + } +} + +async function sodiumEncryptedSeal() { + const pubKey = document.querySelector("#pubKey") as HTMLInputElement; + const privKey = document.querySelector("#privKey") as HTMLInputElement; + const plainKey = document.querySelector("#plainKey") as HTMLInputElement; + const cipherKey = document.querySelector(CYPHER_KEY) as HTMLInputElement; + try { + await _sodium.ready; + const sodium = _sodium; + + if (!privKey.value && !pubKey.value) { + statusToggle("error", `Error: You need to enter either public or private key.`); + return; + } + if (!pubKey.value && privKey.value) { + // derive public key from private key + const binPriv = sodium.from_base64(privKey.value, sodium.base64_variants.URLSAFE_NO_PADDING); + const binPub = sodium.crypto_scalarmult_base(binPriv); + const output = sodium.to_base64(binPub, sodium.base64_variants.URLSAFE_NO_PADDING); + pubKey.value = output; + } + const binkey = sodium.from_base64(pubKey.value, sodium.base64_variants.URLSAFE_NO_PADDING); + const binsec = sodium.from_string(plainKey.value); + const encBytes = sodium.crypto_box_seal(binsec, binkey); + const output = sodium.to_base64(encBytes, sodium.base64_variants.URLSAFE_NO_PADDING); + cipherKey.value = output; + statusToggle("success", `Success: Key Encryption is ok.`); + } catch (error: unknown) { + if (error instanceof Error) { + statusToggle("error", `Error: ${error.message}`); + } else { + statusToggle("error", `Error: ${JSON.stringify(error)}`); + } + } +} + +async function sodiumOpenSeal() { + const pubKey = document.querySelector("#pubKey") as HTMLInputElement; + const privKey = document.querySelector("#privKey") as HTMLInputElement; + const cipherKey = document.querySelector("#cipherKey") as HTMLInputElement; + const plainKey = document.querySelector("#plainKey") as HTMLInputElement; + try { + await _sodium.ready; + const sodium = _sodium; + + if (!privKey.value) { + statusToggle("error", `Error: You need to enter private key.`); + return; + } + if (!pubKey.value && privKey.value) { + // derive public key from private key + const binPriv = sodium.from_base64(privKey.value, sodium.base64_variants.URLSAFE_NO_PADDING); + const binPub = sodium.crypto_scalarmult_base(binPriv); + const output = sodium.to_base64(binPub, sodium.base64_variants.URLSAFE_NO_PADDING); + pubKey.value = output; + } + const binPub = sodium.from_base64(pubKey.value, sodium.base64_variants.URLSAFE_NO_PADDING); + const binPriv = sodium.from_base64(privKey.value, sodium.base64_variants.URLSAFE_NO_PADDING); + const binCipher = sodium.from_base64(cipherKey.value, sodium.base64_variants.URLSAFE_NO_PADDING); + const outText = sodium.crypto_box_seal_open(binCipher, binPub, binPriv, "text"); + plainKey.value = outText; + statusToggle("success", `Success: Key Decryption is ok.`); + } catch (error: unknown) { + if (error instanceof Error) { + statusToggle("error", `Error: ${error.message}`); + } else { + statusToggle("error", `Error: ${JSON.stringify(error)}`); + } + } +} + +function init() { + const genBtn = document.querySelector("#genBtn") as HTMLButtonElement; + const encryptBtn = document.querySelector("#encryptBtn") as HTMLButtonElement; + const decryptBtn = document.querySelector("#decryptBtn") as HTMLButtonElement; + + genBtn.addEventListener("click", () => { + sodiumKeyBox().catch((error) => { + statusToggle("error", `Error: ${error.message}`); + }); + }); + + encryptBtn.addEventListener("click", () => { + sodiumEncryptedSeal().catch((error) => { + statusToggle("error", `Error: ${error.message}`); + }); + }); + + decryptBtn.addEventListener("click", () => { + sodiumOpenSeal().catch((error) => { + statusToggle("error", `Error: ${error.message}`); + }); + }); +} + +init(); diff --git a/yarn.lock b/yarn.lock index 9be1cc3..ffacf86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3052,6 +3052,18 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +libsodium-wrappers@^0.7.13: + version "0.7.13" + resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.13.tgz#83299e06ee1466057ba0e64e532777d2929b90d3" + integrity sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw== + dependencies: + libsodium "^0.7.13" + +libsodium@^0.7.13: + version "0.7.13" + resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.13.tgz#230712ec0b7447c57b39489c48a4af01985fb393" + integrity sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw== + lilconfig@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc"