Use random.org to choose the random pad values

This commit is contained in:
Robbie Antenesse 2018-02-22 16:36:46 -07:00
parent b931f18f03
commit 6fb8494c8f
14 changed files with 757 additions and 38 deletions

View File

@ -1,7 +1,10 @@
# One-Time Pad Generator # One-Time Pad Generator
Encrypt messages with a randomly-generated [one-time pad](https://en.wikipedia.org/wiki/One-time_pad)! Send your encrypted message along with your pad, Encrypt messages with a randomly-generated [one-time pad](https://en.wikipedia.org/wiki/One-time_pad)!
and your friend can decrypt the message. Just be sure you destroy the pad when you're done! Send your encrypted message along with your pad, and your friend can decrypt the message.
Just be sure you destroy the pad when you're done!
Uses [Random.org](https://www.random.org) to generate a truly random one-time pad.
## Installation ## Installation

File diff suppressed because one or more lines are too long

View File

@ -1,3 +0,0 @@
require=function(r,e,n){function t(n,o){function i(r){return t(i.resolve(r))}function f(e){return r[n][1][e]||e}if(!e[n]){if(!r[n]){var c="function"==typeof require&&require;if(!o&&c)return c(n,!0);if(u)return u(n,!0);var l=new Error("Cannot find module '"+n+"'");throw l.code="MODULE_NOT_FOUND",l}i.resolve=f;var s=e[n]=new t.Module(n);r[n][0].call(s.exports,i,s,s.exports)}return e[n].exports}function o(r){this.id=r,this.bundle=t,this.exports={}}var u="function"==typeof require&&require;t.isParcelRequire=!0,t.Module=o,t.modules=r,t.cache=e,t.parent=u;for(var i=0;i<n.length;i++)t(n[i]);return t}({4:[function(require,module,exports) {
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","&","$"],t=exports.generatePad=function(t){for(var n=[],u=0;u<t;u++){var a=Math.floor(Math.random()*e.length);n.push(e[a])}return n},n=function(e){return e.replace(/[\s]+/g,"&").replace(/[^a-zA-Z0-9\&]/g,"$")},u=exports.encrypt=function(u){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,d=n(u).toUpperCase();return{oneTimePad:a=a||t(d.length),encryptedMessage:a.map(function(t,n){var u=d.charAt(n),a=""!==u?e.indexOf(u):e.length-1,r=e.indexOf(t);return e[(a+r)%e.length]}).join("")}},a=exports.decrypt=function(t,n){return t=t.toUpperCase(),n.map(function(n,u){for(var a=e.indexOf(t.charAt(u))-e.indexOf(n);a<0;)a+=e.length;return e[a%e.length]}).join("").replace(/\&/g," ").replace(/\$/g,"-")};window.onload=function(){document.getElementById("encryptInput").onclick=function(){var e=document.getElementById("inputError"),t=document.getElementById("input").value,a=n(document.getElementById("inputPad").value).toUpperCase(),d=""!==a?a.split(""):null;if(null!==d&&d.length<t.length)document.getElementById("inputPad").value=d.join(""),e.innerHTML="The pad must be at least as long as the input";else{e.innerHTML="";var r=u(t,d);document.getElementById("inputPad").value=r.oneTimePad.join(""),document.getElementById("encrypted").innerHTML=r.encryptedMessage}},document.getElementById("decryptInput").onclick=function(){var e=document.getElementById("encryptedInput").value,t=document.getElementById("encryptedInputPad").value.split(""),n=a(e,t);document.getElementById("decrypted").innerHTML=n},document.getElementById("padLength").oninput=function(e){parseInt(e.target.value)<1&&(e.target.value=1)},document.getElementById("generatePad").onclick=function(){var e=document.getElementById("padLength");""===e.value&&(e.value="10");var n=parseInt(e.value,10),u=t(n);document.getElementById("inputPad").value=u.join("")},document.getElementById("clearPad").onclick=function(){document.getElementById("padLength").value="",document.getElementById("inputPad").value=""}};
},{}]},{},[4])

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 434 KiB

View File

@ -1,3 +1,3 @@
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>One-Time Pad Generator</title> <meta name="description" content="One-Time Pad Generator"> <link rel="stylesheet" href="c612cd5e7d7f16f744f6cbfb390e8362.css"> <link rel="stylesheet" href="8e744682420400baa41f79ace446de2c.css"> <style>pre{word-break:break-all;white-space:pre-wrap}</style> <!--[if lt IE 9]> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>One-Time Pad Generator</title> <meta name="description" content="One-Time Pad Generator"> <link rel="stylesheet" href="2d72691b72b80268e116b606ca55ce89.css"> <link rel="stylesheet" href="f8167f18c4f78a03b0feca8921b96daa.css"> <style>pre{word-break:break-all;white-space:pre-wrap}</style> <!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]--> </head> <body> <div class="section"> <div class="container"> <div class="columns"> <div class="column"> <h2 class="title"> Encrypt a Message </h2> <div class="field"> <label class="label"> Your Message <div class="control"> <textarea id="input" class="textarea"></textarea> </div> </label> </div> <div class="control"> <label class="label"> One-Time Pad </label> </div> <div class="field has-addons is-small"> <div class="control"> <input class="input is-small" type="number" id="padLength" placeholder="Length"> </div> <div class="control"> <a class="button is-small" id="generatePad"> <span> Generate Pad </span> <span class="icon is-small"> <i class="fa fa-lock"></i> </span> </a> </div> <div class="control"> <a class="button is-small is-danger" id="clearPad"> <span> Clear Pad </span> <span class="icon is-small"> <i class="fa fa-asterisk"></i> </span> </a> </div> </div> <div class="control"> <textarea id="inputPad" class="textarea"></textarea> <div class="help is-danger" id="inputError"></div> </div> <div class="field"> <div class="control"> <a class="button" id="encryptInput"> <span> Encrypt </span> <span class="icon"> <i class="fa fa-lock"></i> </span> </a> </div> </div> <div class="columns"> <div class="column"> <label class="label">Encrypted Message</label> <div class="box"> <pre id="encrypted"></pre> </div> </div> </div> </div> <div class="column"> <h2 class="title"> Decrypt a Message </h2> <div class="field"> <label class="label"> Their Message <div class="control"> <textarea id="encryptedInput" class="textarea"></textarea> </div> </label> </div> <div class="field"> <label class="label"> One-Time Pad <div class="control"> <textarea id="encryptedInputPad" class="textarea"></textarea> </div> <div class="help is-error" id="inputError"></div> </label> </div> <div class="field"> <div class="control"> <a class="button" id="decryptInput"> <span> Decrypt </span> <span class="icon"> <i class="fa fa-unlock"></i> </span> </a> </div> </div> <div class="columns"> <div class="column"> <label class="label">Decrypted Message</label> <div class="box"> <pre id="decrypted"></pre> </div> </div> </div> </div> </div> </div> </div> <script src="af63cea32e54b78eeda13c0231ff431e.js"></script> </body> </html> <![endif]--> </head> <body> <div class="section"> <div class="container"> <div class="columns"> <div class="column"> <h2 class="title"> Encrypt a Message </h2> <div class="field"> <label class="label"> Your Message <div class="control"> <textarea id="input" class="textarea"></textarea> </div> </label> </div> <div class="control"> <label class="label"> One-Time Pad </label> </div> <div class="field has-addons is-small"> <div class="control"> <input class="input is-small" type="number" id="padLength" placeholder="Length"> </div> <div class="control"> <a class="button is-small" id="generatePad"> <span> Generate Pad </span> <span class="icon is-small"> <i class="fa fa-lock"></i> </span> </a> </div> <div class="control"> <a class="button is-small is-danger" id="clearPad"> <span> Clear Pad </span> <span class="icon is-small"> <i class="fa fa-asterisk"></i> </span> </a> </div> </div> <div class="control"> <textarea id="inputPad" class="textarea"></textarea> <div class="help is-danger" id="inputError"></div> </div> <div class="field"> <div class="control"> <a class="button" id="encryptInput"> <span> Encrypt </span> <span class="icon"> <i class="fa fa-lock"></i> </span> </a> </div> </div> <div class="columns"> <div class="column"> <label class="label">Encrypted Message</label> <div class="box"> <pre id="encrypted"></pre> </div> </div> </div> </div> <div class="column"> <h2 class="title"> Decrypt a Message </h2> <div class="field"> <label class="label"> Their Message <div class="control"> <textarea id="encryptedInput" class="textarea"></textarea> </div> </label> </div> <div class="field"> <label class="label"> One-Time Pad <div class="control"> <textarea id="encryptedInputPad" class="textarea"></textarea> </div> <div class="help is-error" id="inputError"></div> </label> </div> <div class="field"> <div class="control"> <a class="button" id="decryptInput"> <span> Decrypt </span> <span class="icon"> <i class="fa fa-unlock"></i> </span> </a> </div> </div> <div class="columns"> <div class="column"> <label class="label">Decrypted Message</label> <div class="box"> <pre id="decrypted"></pre> </div> </div> </div> </div> </div> </div> </div> <script src="c78a0231a6d0c69eb078bc96cafd649c.js"></script> </body> </html>

View File

@ -1,3 +1,6 @@
import 'babel-polyfill';
import 'whatwg-fetch';
const CHARS = [ const CHARS = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
@ -6,12 +9,8 @@ const CHARS = [
]; ];
export const generatePad = (length) => { export const generatePad = (length) => {
const pad = []; return fetch(`https://www.random.org/integers/?num=${length}&min=0&max=${CHARS.length - 1}&col=1&base=10&format=plain&rnd=new`)
for (let i = 0; i < length; i++) { .then(response => response.text()).then(text => text.split('\n').map(number => CHARS[parseInt(number)]));
const letter = Math.floor(Math.random() * CHARS.length);
pad.push(CHARS[letter]);
}
return pad;
} }
const stripString = (string) => { const stripString = (string) => {
@ -20,31 +19,35 @@ const stripString = (string) => {
export const encrypt = (string, pad = null) => { export const encrypt = (string, pad = null) => {
const strippedString = stripString(string).toUpperCase(); const strippedString = stripString(string).toUpperCase();
pad = pad ? pad : generatePad(strippedString.length); const padPromise = pad ? Promise.resolve(pad) : generatePad(strippedString.length);
return { return padPromise.then(pad => {
oneTimePad: pad, return {
encryptedMessage: pad.map((letter, index) => { oneTimePad: pad,
const messageLetter = strippedString.charAt(index); encryptedMessage: pad.map((letter, index) => {
const letterValue = messageLetter !== '' ? CHARS.indexOf(messageLetter) : CHARS.length - 1; const messageLetter = strippedString.charAt(index);
const padValue = CHARS.indexOf(letter); const letterValue = messageLetter !== '' ? CHARS.indexOf(messageLetter) : CHARS.length - 1;
return CHARS[(letterValue + padValue) % CHARS.length]; const padValue = CHARS.indexOf(letter);
}).join(''), return CHARS[(letterValue + padValue) % CHARS.length];
}; }).join(''),
};
});
} }
export const decrypt = (string, pad) => { export const decrypt = (string, pad) => {
string = string.toUpperCase(); string = string.toUpperCase();
return pad.map((letter, index) => { const message = pad.map((letter, index) => {
const letterValue = CHARS.indexOf(string.charAt(index)); const letterValue = CHARS.indexOf(string.charAt(index));
const padValue = CHARS.indexOf(letter); const padValue = CHARS.indexOf(letter);
let charIndex = (letterValue - padValue); let charIndex = (letterValue - padValue);
while (charIndex < 0) {charIndex += CHARS.length} while (charIndex < 0) {charIndex += CHARS.length}
return CHARS[charIndex % CHARS.length]; return CHARS[charIndex % CHARS.length];
}).join('').replace(/\&/g, ' ').replace(/\$/g, '-'); }).join('').replace(/\&/g, ' ').replace(/\$/g, '-');
return Promise.resolve(message);
} }
window.onload = () => { window.onload = () => {
document.getElementById('encryptInput').onclick = () => { const encryptButton = document.getElementById('encryptInput');
encryptButton.onclick = () => {
const error = document.getElementById('inputError'); const error = document.getElementById('inputError');
const input = document.getElementById('input').value; const input = document.getElementById('input').value;
const inputPad = stripString(document.getElementById('inputPad').value).toUpperCase(); const inputPad = stripString(document.getElementById('inputPad').value).toUpperCase();
@ -54,17 +57,24 @@ window.onload = () => {
error.innerHTML = 'The pad must be at least as long as the input'; error.innerHTML = 'The pad must be at least as long as the input';
} else { } else {
error.innerHTML = ''; error.innerHTML = '';
const encryption = encrypt(input, pad); encryptButton.classList.add('is-loading');
document.getElementById('inputPad').value = encryption.oneTimePad.join(''); encryptButton.disabled = true;
document.getElementById('encrypted').innerHTML = encryption.encryptedMessage; encrypt(input, pad).then(encryption => {
document.getElementById('padLength').value = encryption.oneTimePad.length;
document.getElementById('inputPad').value = encryption.oneTimePad.join('');
document.getElementById('encrypted').innerHTML = encryption.encryptedMessage;
encryptButton.classList.remove('is-loading');
encryptButton.disabled = false;
});
} }
} }
document.getElementById('decryptInput').onclick = () => { document.getElementById('decryptInput').onclick = () => {
const input = document.getElementById('encryptedInput').value; const input = document.getElementById('encryptedInput').value;
const pad = document.getElementById('encryptedInputPad').value.split(''); const pad = document.getElementById('encryptedInputPad').value.split('');
const output = decrypt(input, pad); decrypt(input, pad).then(output => {
document.getElementById('decrypted').innerHTML = output; document.getElementById('decrypted').innerHTML = output;
});
} }
document.getElementById('padLength').oninput = (event) => { document.getElementById('padLength').oninput = (event) => {
@ -72,14 +82,20 @@ window.onload = () => {
if (value < 1) event.target.value = 1; if (value < 1) event.target.value = 1;
} }
document.getElementById('generatePad').onclick = () => { const generatePadButton = document.getElementById('generatePad');
generatePadButton.onclick = () => {
const field = document.getElementById('padLength'); const field = document.getElementById('padLength');
if (field.value === '') { if (field.value === '') {
field.value = '10'; field.value = '10';
} }
const length = parseInt(field.value, 10); const length = parseInt(field.value, 10);
const output = generatePad(length); generatePadButton.classList.add('is-loading');
document.getElementById('inputPad').value = output.join(''); generatePadButton.disabled = true;
generatePad(length).then(output => {
document.getElementById('inputPad').value = output.join('');
generatePadButton.classList.remove('is-loading');
generatePadButton.disabled = false;
});
} }
document.getElementById('clearPad').onclick = () => { document.getElementById('clearPad').onclick = () => {

View File

@ -6,14 +6,17 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "parcel ./index.html", "dev": "parcel ./index.html",
"build": "parcel build ./index.html --out-dir docs --public-url ./" "build": "rimraf docs && parcel build ./index.html --out-dir docs --public-url ./"
}, },
"devDependencies": { "devDependencies": {
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",
"parcel-bundler": "^1.6.2" "parcel-bundler": "^1.6.2",
"rimraf": "^2.6.2"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "^6.26.0",
"bulma": "^0.6.2", "bulma": "^0.6.2",
"font-awesome": "^4.7.0" "font-awesome": "^4.7.0",
"whatwg-fetch": "^2.0.3"
} }
} }

View File

@ -539,6 +539,14 @@ babel-plugin-transform-strict-mode@^6.24.1:
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-types "^6.24.1" babel-types "^6.24.1"
babel-polyfill@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
dependencies:
babel-runtime "^6.26.0"
core-js "^2.5.0"
regenerator-runtime "^0.10.5"
babel-preset-env@^1.6.1: babel-preset-env@^1.6.1:
version "1.6.1" version "1.6.1"
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48"
@ -2990,6 +2998,10 @@ regenerate@^1.2.1:
version "1.3.3" version "1.3.3"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f"
regenerator-runtime@^0.10.5:
version "0.10.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
regenerator-runtime@^0.11.0: regenerator-runtime@^0.11.0:
version "0.11.1" version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
@ -3096,7 +3108,7 @@ right-align@^0.1.1:
dependencies: dependencies:
align-text "^0.1.1" align-text "^0.1.1"
rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1, rimraf@^2.6.2:
version "2.6.2" version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies: dependencies:
@ -3701,6 +3713,10 @@ vm-browserify@0.0.4:
dependencies: dependencies:
indexof "0.0.1" indexof "0.0.1"
whatwg-fetch@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
whet.extend@~0.9.9: whet.extend@~0.9.9:
version "0.9.9" version "0.9.9"
resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"