Skip to content

Commit

Permalink
RC1
Browse files Browse the repository at this point in the history
  • Loading branch information
ptmrio committed Apr 6, 2023
1 parent 201e5a7 commit c76cc9b
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 62 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Send Password Online
# Share Password Online

Send Password Online is a simple web application that allows users to securely share encrypted messages with a passphrase. The recipient can decrypt the message by entering the passphrase.
Share Password Online is a simple web application that allows users to securely share encrypted messages with a passphrase. The recipient can decrypt the message by entering the passphrase.

## DEMO

[https://sharepassword.online/](https://sharepassword.online)

## Features

Expand Down
168 changes: 121 additions & 47 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Send Password Online</title>
<title>Share Password Online</title>
<style type="text/css">
/* Reset some default styles */
* {
Expand All @@ -28,28 +28,13 @@
--gap: 1rem;
}

.even-spacing {
--gap: 1rem;
display: grid;
gap: var(--gap);
}

.even-spacing--large {
--gap: 2rem;
}

.even-spacing--small {
--gap: 0.2rem;
}

body {
place-items: center;
align-content: center;
min-height: 100dvh;
font-family: Arial, sans-serif;
line-height: 1.6;
background-color: var(--background-color);
padding: var(--gap);
color: var(--text-color);
}

Expand All @@ -64,7 +49,6 @@

form {
background-color: var(--form-background-color);
padding: var(--gap);
border-radius: var(--border-radius);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
width: 100%;
Expand All @@ -77,7 +61,7 @@
}

input {
font-size: 1rem;
font-size: 1.25rem;
padding: 5px;
width: 100%;
border: 1px solid var(--input-border-color);
Expand All @@ -90,22 +74,30 @@
}

button {
transition: all 0.3s ease;
}
--button-color: #333;
--button-background-color: #ccc;
--button-background-color-hover: #bbb;

button[type="submit"] {
background-color: var(--button-background-color);
color: var(--button-color);
justify-self: center;
background-color: var(--accent-color);
color: #fff;
font-size: 1rem;
padding: 10px;
padding: calc(var(--gap) / 1.5) var(--gap);
border: none;
border-radius: var(--border-radius);
cursor: pointer;
transition: all 0.3s ease;
}

button[type="submit"]:hover {
background-color: var(--accent-color-dark);
button:hover {
background-color: var(--button-background-color-hover);
}

button[type="submit"] {
--button-color: #fff;
--button-background-color: var(--accent-color);
--button-background-color-hover: var(--accent-color-dark);

}

dialog {
Expand Down Expand Up @@ -140,20 +132,20 @@
opacity: 0;
}

button[data-id="close-dialog"] {
background-color: #ccc;
color: #333;
font-size: 1rem;
padding: 10px;
border: none;
border-radius: var(--border-radius);
cursor: pointer;
display: block;
width: 100%;
/* Utility classes */
.even-spacing {
--gap: 1rem;
display: grid;
gap: var(--gap);
padding: var(--gap);
}

button[data-id="close-dialog"]:hover {
background-color: #bbb;
.even-spacing--large {
--gap: 2rem;
}

.even-spacing--small {
--gap: 0.2rem;
}

.text {
Expand All @@ -166,6 +158,79 @@
text-align: center;
}

/* Validation */
form.validated input:valid {
--hue: 122;
--saturation: 39%;
--lightness: 49%;
border-color: hsla(var(--hue), var(--saturation), var(--lightness), 0.5);
outline: none;
background-color: hsla(var(--hue), var(--saturation), var(--lightness), 0.1);
}

form.validated input:invalid {
--hue: 4;
--saturation: 90%;
--lightness: 58%;
border-color: hsla(var(--hue), var(--saturation), var(--lightness), 0.5);
outline: none;
background-color: hsla(var(--hue), var(--saturation), var(--lightness), 0.1);
}

form.validated input:hover,
form.validated input:focus {
box-shadow: 0 2px 5px hsla(var(--hue), var(--saturation), var(--lightness), 0.5);
}


/* Components */

/* Components: ToolTip */
.tooltip-container {
display: inline-flex;
position: relative;
align-items: center;
justify-content: center;
cursor: pointer;
}

.tooltip {
position: absolute;
bottom: calc(100% + 10px);
left: 50%;
transform: translateX(-50%);
transition: opacity 0.3s ease-in-out;
opacity: 0;
pointer-events: none;
}

.tooltip-container.active .tooltip {
opacity: 1;
}

.tooltip-inner {
background-color: rgba(0, 0, 0, 0.8);
color: #fff;
padding: 5px 10px;
border-radius: 3px;
font-size: 0.8rem;
white-space: nowrap;
}

.tooltip::before {
content: "";
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border-width: 5px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.8) transparent transparent transparent;
}


/* Animations */

@keyframes fade-in {
0% {
opacity: 0;
Expand Down Expand Up @@ -226,19 +291,19 @@
</head>

<body class="even-spacing even-spacing--large">
<h1>Send Password Online</h1>
<h1>Share Password Online</h1>

<p class="text text-center">Sharing passwords over the internet is never a great idea.
However if you absolutely have to do it, use this page to encrypt your secret (password, credit card number, etc.) and share the newly created link and the passphrase using two separate ways (e.g. Text and Phone, WhatsApp and Signal, Slack and In-Person-Communication). The receiver now can decrypt the secret with the passphrase you provided.</p>

<form class="even-spacing" data-id="encryption-form">
<form class="even-spacing" data-id="encryption-form" novalidate>
<div class="even-spacing even-spacing--small" data-id="secret-container">
<label for="message">Secret:</label>
<input type="text" data-id="message" name="message" autocomplete="false" autofocus="true">
<input type="text" data-id="message" name="message" required maxlength="512" autocomplete="off" autofocus="true">
</div>
<div class="even-spacing even-spacing--small">
<label for="passphrase">Passphrase:</label>
<input type="password" data-id="passphrase" name="passphrase">
<input type="password" data-id="passphrase" name="passphrase" required>
</div>
<button type="submit">Generate Link</button>
</form>
Expand All @@ -250,22 +315,31 @@ <h2>How does this work?</h2>
</div>
<div class="even-spacing even-spacing--small">
<h2>Is this safe?</h2>
<p>Encryption, link generation and decryption happens 100% on the client side. Nothing is stored or tracked. Just plain vanilla javascript! Right-click and inspect the code yourself or got GitHub to inspect it there. As long as your device and the device of the receipient is safe, this should be a pretty secure way to send and receive passwords.</p>
<p>Encryption, link generation and decryption happens 100% on the client side. Nothing is stored or tracked. Just plain vanilla javascript! Right-click and inspect the code yourself or <a href="https://github.com/ptmrio/SharePasswordOnline">go to GitHub to inspect it there</a>. As long as your device and the device of the receipient is safe, this should be a pretty secure way to send
and receive passwords.</p>
<p>But please, still be careful. Share secrets only with people you trust!</p>
</div>
<div class="even-spacing even-spacing--small">
<h2>Thanks, can I contribue?</h2>
<p>You may contribute on GitHub. Or may I suggest you buy me a beer?</p>
<p>PayPal: paypal.me/g.petermeir</p>
<p>Bitcoin Address: x0123</p>
<p>You may contribute on <a href="https://github.com/ptmrio/SharePasswordOnline">GitHub</a>. Or may I suggest you buy me a beer?</p>
<p>PayPal: <a href="https://www.paypal.com/paypalme/my/profile">paypal.me/Petermeir</a></p>
<p>Bitcoin Address: 3JzyeyJBhRws83PdiiaQ2KzcCZPZumnigX</p>
</div>
</div>

<dialog class="even-spacing" data-id="link-dialog">
<h2>Generated Link</h2>
<div class="even-spacing even-spacing--small">
<p>Copy this link and send it via your preferred method. Tell him the passphrase in a separate way, to protect the secret:</p>
<input type="text" data-id="generated-link" readonly>
<div class="tooltip-container">
<input type="text" data-id="generated-link" readonly>
<div class="tooltip">
<div class="tooltip-inner">
Copied!
</div>
</div>
</div>

</div>
<button data-id="close-dialog">Close</button>
</dialog>
Expand Down
46 changes: 33 additions & 13 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,21 @@ document.addEventListener('DOMContentLoaded', () => {
const message = messageInput.value;
const passphrase = passphraseInput.value;

if (passphrase) {
// validate the message and passphrase
encryptionForm.classList.add('validated');
encryptionForm.reportValidity();

if (encryptionForm.checkValidity() && passphrase) {

if (!urlParams.has('encryptedMessage')) {
const encryptedMessage = await encryptMessage(message, passphrase);
const link = generateLink(encryptedMessage);
if (!urlParams.has('encryptedSecret')) {
const encryptedSecret = await encryptSecret(message, passphrase);
const link = generateLink(encryptedSecret);
generatedLinkInput.value = link;
showDialog(linkDialog); // Show the dialog
} else {
decryptMessage(urlParams.get('encryptedMessage'), passphrase).then((decryptedMessage) => {
decryptSecret(urlParams.get('encryptedSecret'), passphrase).then((decryptedMessage) => {
messageInput.value = decryptedMessage;
secretContainer.style.display = 'block';
secretContainer.style.display = 'grid';
setTimeout(() => {
secretContainer.style.opacity = '1';
secretContainer.classList.add('shake');
Expand All @@ -39,20 +43,20 @@ document.addEventListener('DOMContentLoaded', () => {

// Encrypt and Decrypt functions remain unchanged

function generateLink(encryptedMessage) {
return `https://sendpassword.online/?encryptedMessage=${encodeURIComponent(encryptedMessage)}`;
function generateLink(encryptedSecret) {
return `https://sharepassword.online/?encryptedSecret=${encodeURIComponent(encryptedSecret)}`;
}

const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('encryptedMessage')) {
if (urlParams.has('encryptedSecret')) {
secretContainer.style.display = 'none';
secretContainer.style.opacity = '0';
messageInput.readOnly = true;
submitButton.textContent = 'Decrypt';
}


async function encryptMessage(message, passphrase) {
async function encryptSecret(message, passphrase) {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const passphraseKey = await window.crypto.subtle.importKey(
Expand All @@ -78,8 +82,8 @@ document.addEventListener('DOMContentLoaded', () => {
}


async function decryptMessage(encryptedMessage, passphrase) {
const [encryptedDataB64, ivB64] = encryptedMessage.split('.');
async function decryptSecret(encryptedSecret, passphrase) {
const [encryptedDataB64, ivB64] = encryptedSecret.split('.');
const encryptedData = Uint8Array.from(atob(encryptedDataB64), c => c.charCodeAt(0));
const iv = Uint8Array.from(atob(ivB64), c => c.charCodeAt(0));

Expand Down Expand Up @@ -126,7 +130,23 @@ document.addEventListener('DOMContentLoaded', () => {
}

closeDialogButton.addEventListener('click', () => {
closeDialog(linkDialog); // Close the dialog
closeDialog(linkDialog);
});


generatedLinkInput.addEventListener('click', () => {
const tooltipContainer = generatedLinkInput.closest('.tooltip-container');

generatedLinkInput.select();
generatedLinkInput.setSelectionRange(0, 99999);

document.execCommand('copy');

tooltipContainer.classList.add('active');

setTimeout(() => {
tooltipContainer.classList.remove('active');
}, 2000);
});

});

0 comments on commit c76cc9b

Please sign in to comment.