A Pen by Artur Mustafin on CodePen.
Last active
August 18, 2019 14:34
-
-
Save default-work/6d384664bcd0c13a1fc60300920d6fc0 to your computer and use it in GitHub Desktop.
Caesar Cipher + 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h1>Caesar Cipher +1</h1> | |
<table> | |
<tr> | |
<td style="width:50%;"> | |
<label>Plaintext:</label> | |
<textarea id='plaintext1'>The atmosphere of Mars is about 100 times thinner than Earth's, and it is 95 percent carbon dioxide. Here's a breakdown of its composition, according to a NASA fact sheet: | |
Carbon dioxide: 95.32 percent | |
Nitrogen: 2.7 percent | |
Argon: 1.6 percent | |
Oxygen: 0.13 percent | |
Carbon monoxide: 0.08 percent | |
Also, minor amounts of: water, nitrogen oxide, neon, hydrogen-deuterium-oxygen, krypton and xenon.</textarea> | |
<label>Shift:</label> | |
<input type='number' id='shift1' name='shift' value='88' min='1' max='9999' step='1'> | |
<input type='button' id='randomize' value='IV'> | |
<input type='button' id='alphabet_random' value='alphabet'> | |
<input type='button' id='encrypt' value='encrypt'> | |
<input type='button' id='apply' value='=>'> | |
<textarea id='IV1'></textarea> | |
<textarea id='alphabet1'></textarea> | |
</td> | |
<td style="width:50%"> | |
<label>Cipher:</label> | |
<textarea id='plaintext2'></textarea> | |
<label>Shift:</label> | |
<input type='number' id='shift2' name='shift' value='88' min='1' max='9999' step='1'> | |
<input type='button' id='decrypt' value='decrypt'> | |
<textarea id='IV2'></textarea> | |
<textarea id='alphabet2'></textarea> | |
</td> | |
</tr> | |
</table> | |
<h1>Output:</h1> | |
<table> | |
<tr> | |
<td> | |
<textarea id='output1'></textarea> | |
</td> | |
<td> | |
<textarea id='output2'></textarea> | |
</td> | |
</tr> | |
</table> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Artur Mustafin, (c) 2019 | |
// Park & Miller, (c) 1988,1993 | |
const default_alphabet = [ | |
'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',' ',':',',','*', | |
'~','!','@','#','%','^', | |
'-','=','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','"','?','.','_', | |
'+','(',')','[',']','|', | |
'{','}','`','\/' //88 | |
]; | |
let alphabet = default_alphabet; | |
// LCG Park & Miller (c) 1988,1993 (original value proposed was 16807, in 1993 changed to 48271) | |
// s=>()=>(2**31-1&(s=Math.imul(48271,s)))/2**31 | |
var PRNG = function(seed){ | |
this._seed = seed % 2147483647; | |
if (this._seed <= 0){ this._seed += 2147483646;} | |
}; | |
PRNG.prototype.next = function(a,b){ | |
this._seed = this._seed * 48271 % 2147483647; // in response to a criticism by Marsaglia in 1993 | |
if(arguments.length === 0){ | |
return this._seed/2147483647; | |
}else if(arguments.length === 1){ | |
return (this._seed/2147483647)*a; | |
}else{ | |
return (this._seed/2147483647)*(b-a)+a; | |
} | |
}; | |
var seed = 1238473661; | |
var rnd = new PRNG(seed); | |
var random = 0; | |
var maximus = 2147483647 >> 2; | |
var enc_offset = 0; | |
var dec_offset = 0; | |
Array.prototype.shuffle = function(seed) { | |
return shuffle(this, seed); | |
} | |
Array.prototype.unshuffle = function(seed) { | |
return unshuffle(this, seed); | |
} | |
Array.prototype.offset = function(seed) { | |
return offset(this, seed); | |
} | |
Array.prototype.unoffset = function(seed) { | |
return unoffset(this, seed); | |
} | |
function shuffle(array, seed) { | |
let rng = new PRNG(seed); | |
for (let i = array.length - 1; i > 0; i--) { | |
let j = Math.floor(rng.next(i));// Math.random() * (i + 1)); // random index from 0 to i | |
[array[i], array[j]] = [array[j], array[i]]; // swap elements | |
} | |
return array; | |
} | |
function unshuffle(array, seed) { | |
let indexes = []; | |
let rng = new PRNG(seed); | |
for (let i = array.length - 1; i > 0; i--) { | |
let j = Math.floor(rng.next(i)); | |
indexes.push(j); | |
} | |
for (let i = 1; i < array.length; i++) { | |
let j = indexes.pop(); //Math.floor(rng.next(i));// Math.random() * (i + 1)); // random index from 0 to i | |
[array[i], array[j]] = [array[j], array[i]]; // swap elements | |
} | |
return array; | |
} | |
function offset(array, offset) { | |
let length = array.length; | |
for (let i = length - 1; i > 0; i--) { | |
let j = (2*maximus + i + offset)%length; | |
[array[i], array[j]] = [array[j], array[i]]; // swap elements | |
} | |
return array; | |
} | |
function unoffset(array, offset) { | |
let length = array.length; | |
let indexes = []; | |
for (let i = length - 1; i > 0; i--) { | |
let j = (2*maximus + i + offset)%length; | |
indexes.push(j); | |
} | |
for (let i = 1; i < length; i++) { | |
let j = indexes.pop(); | |
[array[i], array[j]] = [array[j], array[i]]; // swap elements | |
} | |
return array; | |
} | |
function randomInteger(min, max) { | |
let rand = min + rnd.next() * (max + 1 - min); | |
return Math.floor(rand); | |
} | |
const cipher_size = alphabet.length; | |
const encrypt = document.getElementById('encrypt'); | |
const decrypt = document.getElementById('decrypt'); | |
const plaintext1 = document.getElementById('plaintext1'); | |
const plaintext2 = document.getElementById('plaintext2'); | |
const output1 = document.getElementById('output1'); | |
const output2 = document.getElementById('output2'); | |
const IV1 = document.getElementById('IV1'); | |
const IV2 = document.getElementById('IV2'); | |
const alpha1 = document.getElementById('alphabet1'); | |
const alpha2 = document.getElementById('alphabet2'); | |
const app = document.getElementById('apply'); | |
const randomize = document.getElementById('randomize'); | |
const alphabet_random = document.getElementById('alphabet_random'); | |
this.random = randomInteger(0,maximus); | |
IV1.value = this.random; | |
randomize.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.random = randomInteger(0,maximus); | |
this.IV1.value = this.random; | |
}); | |
alphabet_random.addEventListener ('click',event => { | |
event.preventDefault(); | |
alphabet = default_alphabet; | |
alphabet.shuffle(this.random); | |
alpha1.value = alphabet.join(''); | |
}); | |
encrypt.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.random = parseInt(this.IV1.value); | |
alphabet = [... alpha1.value]; | |
this.enc_offset = this.random; | |
const shift = Number(shift1.value); | |
let array = [... plaintext1.value ]; | |
for(let i=0; i< shift; i++) | |
array = array.shuffle(this.random).map(char => shift_encrypt(char, shift)); | |
output1.value = array.offset(this.random).join(''); | |
} | |
); | |
app.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.IV2.value = this.IV1.value; | |
shift2.value = shift1.value; | |
alpha2.value = alpha1.value; | |
plaintext2.value = output1.value; | |
output2.value = ''; | |
}); | |
decrypt.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.random = parseInt(this.IV2.value); | |
alphabet = [... alpha2.value]; | |
this.dec_offset = parseInt(this.IV2.value); | |
const shift = Number(shift2.value); | |
let array = [... plaintext2.value ].unoffset(this.random); | |
for(let i=0; i< shift; i++) | |
array = array.map(char => shift_decrypt(char, shift)).unshuffle(this.random); | |
output2.value = array.join(''); | |
} | |
); | |
function shift_encrypt(char, shift) { | |
if (shift%2 == 1) { | |
char = _encrypt(_encrypt(char,alphabet,shift),alphabet,shift); | |
} else { | |
char = _encrypt(_encrypt(char,alphabet.reverse(),0),alphabet.reverse(),0); | |
} | |
return char; | |
} | |
function shift_decrypt(char, shift) { | |
if (shift%2 == 1) { | |
char = _decrypt(_decrypt(char,alphabet,shift),alphabet,shift); | |
} else { | |
char = _decrypt(_decrypt(char,alphabet.reverse(),0),alphabet.reverse(),0); | |
} | |
return char; | |
} | |
function _encrypt(char, alphabet, shift) { | |
if (alphabet.includes(char)) | |
{ | |
const position = alphabet.indexOf(char); | |
const newPosition = (2*maximus - position + this.enc_offset - shift)%cipher_size; | |
this.enc_offset = (++this.enc_offset)%cipher_size; | |
return alphabet[newPosition] | |
} | |
else { return char } | |
} | |
function _decrypt(char, alphabet, shift) { | |
if (alphabet.includes(char)) | |
{ | |
const position = alphabet.indexOf(char); | |
const newPosition = (2*maximus - position - this.dec_offset - shift)%cipher_size; | |
this.dec_offset = (++this.dec_offset)%cipher_size; | |
return alphabet[newPosition] | |
} | |
else { return char } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono&display=swap'); | |
* { | |
font-family: 'Roboto Mono', sans-serif; | |
font-size: 10px; | |
} | |
body { | |
font-family: sans-serif; | |
} | |
h1,h2 { color: olive;} | |
label{display:block;} | |
table { | |
width: 100%; | |
} | |
h1, h2, label, input, textarea { | |
margin: 5px 5px; | |
} | |
textarea { | |
width: calc(100% - 10px); | |
height: 120px; | |
} | |
#alphabet1, #alphabet2, #IV1, #IV2 { | |
height: auto; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment