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
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,
and your friend can decrypt the message. Just be sure you destroy the pad when you're done!
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, 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

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

View File

@ -6,14 +6,17 @@
"license": "MIT",
"scripts": {
"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": {
"babel-preset-env": "^1.6.1",
"parcel-bundler": "^1.6.2"
"parcel-bundler": "^1.6.2",
"rimraf": "^2.6.2"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"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-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:
version "1.6.1"
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"
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:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
@ -3096,7 +3108,7 @@ right-align@^0.1.1:
dependencies:
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"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
@ -3701,6 +3713,10 @@ vm-browserify@0.0.4:
dependencies:
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:
version "0.9.9"
resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"