From 5cd3e3f990a2164cfc1f8596d6584aae60bc2922 Mon Sep 17 00:00:00 2001 From: Silas Date: Mon, 29 Jan 2024 22:41:01 -0500 Subject: [PATCH] bunch of UI cleanup, add MIT license, add readme --- .gitignore | 1 + LICENSE | 8 ++++++++ README.md | 21 ++++++++++++++++++++ index.html | 45 ++++++++++++++++++++++++++++++++++++++++--- src/routes/receive.ts | 25 ++++-------------------- src/routes/request.ts | 15 +++++++-------- src/routes/send.ts | 23 +++++++--------------- 7 files changed, 90 insertions(+), 48 deletions(-) create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore index a547bf3..fc5ae9f 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.vercel diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7e5d2bc --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Copyright 2024 silentsilas + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ee1bc6 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Sure - A Secure Message Sharing Web App + +Sure is a web application that allows you to share secrets securely using end-to-end encryption without relying on a server. It is built with TypeScript, uses ECDH for secure communication between two parties, and works completely offline. + +## Getting Started + +If you have `asdf` installed, run `asdf install` at the root of the project. Otherwise install the version of NodeJS specified in `.tool-versions` in this repository before continuing. + +```bash +git clone https://git.silentsilas.com/silentsilas/sure.git +cd sure +npm install && npm run dev +``` + +## Deploy + +Output a static build to `./dist` that you can deploy to any host, or open `index.html` for a working offline version of the site. + +```bash +npm run build +``` diff --git a/index.html b/index.html index dba1c31..2b8e90e 100644 --- a/index.html +++ b/index.html @@ -40,8 +40,14 @@
-

SURE

-

Secure URL Requests

+

+ SURE +

+

+ Secure + URL + Requests +

@@ -57,7 +63,40 @@ -
+
+
+
+ +
+ How it Works: +
    +
  • Each client generates an ECDH keypair, consisting of a public key and a private key.
  • +
  • Your private key is kept in localStorage, and never leaves your device.
  • +
  • Your public key is embedded in the URLs you generate. This key can be safely shared anywhere without + compromising security.
  • +
  • When another client opens your generated URL, they will find your public ECDH key. They then generate a + random IV for this specific message, and use it, along with their private ECDH key and your public ECDH key, + to derive a shared secret (AES-GCM).
  • +
  • This derived shared secret never leaves their device. It is used to encrypt their message to you. + The encrypted message, along with their public key and the IV for this message, are embedded in the URL they + generate.
  • +
  • Upon opening the response URL, your device uses your private ECDH key, along with the public key and IV + from the URL, to recreate the shared secret. This secret is used to decrypt the message. If the message was + properly encrypted using the expected keys, it will be successfully decrypted and displayed to you.
  • +
  • If you clear your browser's local storage, you will not be able to decrypt any response URLs generated + with your previous unique URL.
  • +
+
+
+
+ + + diff --git a/src/routes/receive.ts b/src/routes/receive.ts index 6bc9902..aa101b6 100644 --- a/src/routes/receive.ts +++ b/src/routes/receive.ts @@ -5,31 +5,21 @@ import { } from "../utils/crypto"; const MESSAGE_OUTPUT_ID = "message"; -const DECRYPT_BUTTON_ID = "decrypt"; const TEMPLATE = ` -
-
- How it Works +
+ How To Use:
    -
  • Press "Decrypt" to view the information sent by the sender.
  • -
  • The decrypted message will appear below.
  • +
  • If someone used your unique URL to generate this response URL, you should see the decrypted message below.
-
-
`; export async function setupReceivePage( @@ -38,14 +28,7 @@ export async function setupReceivePage( ) { element.innerHTML = TEMPLATE; - // Add an event listener to the "Decrypt" button - const decryptButton = document.getElementById( - DECRYPT_BUTTON_ID - ) as HTMLButtonElement; - decryptButton.addEventListener("click", (event: Event) => { - event.preventDefault(); - decryptData(params); - }); + decryptData(params); } async function decryptData({ p, iv, m }: { p: string; iv: string; m: string }) { diff --git a/src/routes/request.ts b/src/routes/request.ts index e95cfd7..a4b48a6 100644 --- a/src/routes/request.ts +++ b/src/routes/request.ts @@ -1,14 +1,13 @@ import { retrieveOrGenerateKeyPair } from "../utils/crypto.ts"; const URL_INPUT_ID = "request-url"; -const TEMPLATE = `
-
- How it Works +const TEMPLATE = ` +
+ How To Use:
    -
  • Send the generated URL below to whom you wish to request data from.
  • -
  • Upon accessing the URL, the receiver can then enter the data you'd like from them.
  • -
  • This generates a URL that they'll send back to you.
  • -
  • You can now access the encrypted data in the URL which only _your_ browser can decrypt.
  • +
  • Share the URL below with whom you'd like to request data from.
  • +
  • When the recipient opens the URL, they will be able to enter the data they'd like to send to you.
  • +
  • They will then generate a new URL with their encrypted data, which only your original device can decrypt.
@@ -22,7 +21,7 @@ const TEMPLATE = `
required /> -
`; + `; export async function setupRequestPage(element: HTMLElement) { element.innerHTML = TEMPLATE; diff --git a/src/routes/send.ts b/src/routes/send.ts index 253aecd..881840b 100644 --- a/src/routes/send.ts +++ b/src/routes/send.ts @@ -9,14 +9,12 @@ const MESSAGE_INPUT_ID = "message"; const ENCRYPT_BUTTON_ID = "encrypt"; const REQUEST_PUBLIC_KEY = "requestPublicKey"; const TEMPLATE = ` -
-
- How it Works +
+ How To Use:
  • Enter the information you'd like to send to the person whom generated this link.
  • -
  • Press "Encrypt" to generate a URL that has your encrypted information.
  • -
  • Send this generated URL to the person who sent this information request.
  • -
  • Only their browser can decrypt the secret in the URL.
  • +
  • Press "Generate Response" to generate a URL below that has your encrypted message.
  • +
  • Send this generated URL back to them, and only their browser can decrypt the message.
@@ -32,18 +30,17 @@ const TEMPLATE = ` -
`; export async function setupSendPage(element: HTMLElement, key: string) { @@ -110,11 +107,5 @@ async function encryptData(event: Event) { ) )}`; - // url.hash = `p=${btoa(JSON.stringify(ecdhPublicJwk))}&iv=${btoa( - // String.fromCharCode.apply(null, Array.from(iv)) - // )}&m=${btoa( - // String.fromCharCode.apply(null, Array.from(new Uint8Array(encryptedData))) - // )}`; - encryptedUrlInput.value = url.toString(); }