A Pen by Artur Mustafin on CodePen.
Forked from default-work/caesar-cipher-1-period-4.markdown
Created
August 18, 2019 06:48
-
-
Save default-writer/8c87cb6c9a24597fe668d236f1e5f6c4 to your computer and use it in GitHub Desktop.
Caesar Cipher + 1 (period 4)
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='256' step='1'><input type='button' id='randomize' value='randomize'> | |
<input type='button' id='encrypt' value='encrypt'> | |
</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='256' step='1'> | |
<input type='button' id='decrypt' value='decrypt'> | |
</td> | |
</tr> | |
<tr style="height: auto"> | |
<td> | |
<textarea id='IV1' style="height: 100%"></textarea> | |
</td> | |
<td> | |
<textarea id='IV2' style="height: 100%"></textarea> | |
</td> | |
</tr> | |
<tr> | |
<td> | |
</td> | |
</tr> | |
</table> | |
<table style="width:100%"> | |
<tr> | |
<td> | |
<input type='button' id='apply' value='=>'> | |
</td> | |
</tr> | |
</table> | |
<h1>Output:</h1> | |
<table> | |
<tr> | |
<td> | |
<textarea id='output1'></textarea> | |
</td> | |
<td> | |
<textarea id='output2'></textarea> | |
</td> | |
</tr> | |
</table> | |
</div> |
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
const 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 | |
]; | |
// 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 indexes = []; | |
let length = array.length; | |
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 app = document.getElementById('apply'); | |
this.random = randomInteger(0,maximus); | |
IV1.value = this.random; | |
const randomize = document.getElementById('randomize'); | |
randomize.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.random = randomInteger(0,maximus); | |
this.IV1.value = this.random; | |
}); | |
app.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.IV2.value = this.IV1.value; | |
shift2.value = shift1.value; | |
plaintext2.value = output1.value; | |
}); | |
encrypt.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.random = parseInt(this.IV1.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(''); | |
} | |
); | |
decrypt.addEventListener ('click',event => { | |
event.preventDefault(); | |
this.random = parseInt(this.IV2.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) { | |
for(let i=0; i<shift; i++) | |
{ | |
if (i%2===1) { | |
char = _encrypt(char,alphabet); | |
} else { | |
char = _encrypt(char,alphabet.reverse()); | |
} | |
} | |
return char; | |
} | |
function shift_decrypt(char, shift) { | |
for(let i=0; i<shift; i++) | |
{ | |
if (i%2===1) { | |
char = _decrypt(char,alphabet); | |
} else { | |
char = _decrypt(char,alphabet.reverse()); | |
} | |
} | |
return char; | |
} | |
function _encrypt(char, alphabet) { | |
if (alphabet.includes(char)) | |
{ | |
const position = alphabet.indexOf(char); | |
const newPosition = (2*maximus + position + this.enc_offset)%cipher_size; | |
this.enc_offset = (++this.enc_offset)%cipher_size; | |
return alphabet[newPosition] | |
} | |
else { return char } | |
} | |
function _decrypt(char, alphabet) { | |
if (alphabet.includes(char)) | |
{ | |
const position = alphabet.indexOf(char); | |
const newPosition = (2*maximus + position - this.dec_offset)%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: 150px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment