Last active
August 29, 2015 14:16
-
-
Save ccckmit/b0a90a7bd9d3d3e5baa8 to your computer and use it in GitHub Desktop.
Revisions
-
ccckmit renamed this gist
Mar 2, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
ccckmit created this gist
Mar 2, 2015 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,122 @@ // 原始程式來源: http://practicalcryptography.com/ciphers/enigma-cipher/ 網頁內的 javascript 程式碼 var c = console; var plaintext = 'ABCDEF'; c.log('>> plaintext2 : '+plaintext); var ciphertext = Encrypt(plaintext, 'AAA', 'AAA', '123', 'POMLIUKJNHYTGBVFREDC'); c.log('>> ciphertext : '+ciphertext); var plaintext2 = Encrypt(ciphertext, 'AAA', 'AAA', '123', 'POMLIUKJNHYTGBVFREDC'); c.log('>> plaintext2 : '+plaintext); function Encrypt(plaintext, keysettings, ringsettings, rotorsettings, plugboardsettings) { c.log('plaintext='+plaintext); c.log('keysetting='+keysettings); c.log('ringsetting='+ringsettings); c.log('plugboardsettings='+plugboardsettings+' len='+plugboardsettings.length); c.log('rotorsettings='+rotorsettings); // do some error checking if(plaintext.length < 1){ c.log("please enter some plaintext (letters and numbers only)"); return; } if(keysettings.length != 3){ c.log("Key settings must consist of 3 uppercase characters."); return; } if(ringsettings.length != 3){ c.log("Ring settings must consist of 3 uppercase characters."); return; } if(plugboardsettings.length > 26){ c.log("There cannot be more than 13 pairs in the plugboard settings."); return; } if(plugboardsettings.length % 2 != 0){ c.log("There must be an even number of characters in the plugboard settings."); return; } if(rotorsettings.length != 3){ c.log("Rotor settings must consist of 3 numbers 1-9."); return; } // interpret the rotor settings (strings 1-8 to int 0-7) var rotors = rotorsettings.split(""); rotors[0]=rotors[0].valueOf()-1;rotors[1]=rotors[1].valueOf()-1;rotors[2]=rotors[2].valueOf()-1; // parse plugboard settings, store as a simple substitution key var plugboard = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var parr = plugboard.split(""); for(i=0,j=1;i<plugboardsettings.length;i+=2,j+=2){ ichar = plugboard.indexOf(plugboardsettings.charAt(i)); jchar = plugboard.indexOf(plugboardsettings.charAt(j)); temp = parr[jchar]; parr[jchar]=parr[ichar]; parr[ichar]=temp; } plugboard = parr.join(""); // interpret key and ring settings (convert from letters to numbers 0-25) key=keysettings.split(""); key[0]=code(key[0]); key[1]=code(key[1]); key[2]=code(key[2]); ring=ringsettings.split(""); ring[0]=code(ring[0]); ring[1]=code(ring[1]); ring[2]=code(ring[2]); // do the actual enigma enciphering ciphertext = ""; for(i=0; i < plaintext.length; i++){ ch=plaintext.charAt(i); // if the current character is not a letter, pass it through unchanged if(!ch.match(/[A-Z]/)){ ciphertext = ciphertext + ch; }else{ key=increment_settings(key,rotors); ciphertext = ciphertext + enigma(ch,key,rotors,ring,plugboard); } } c.log('ciphertext='+ciphertext); return ciphertext; } function enigma(ch,key,rotors,ring,plugboard){ // apply plugboard transformation ch = simplesub(ch,plugboard); // apply rotor transformations from right to left ch = rotor(ch,rotors[2],key[2]-ring[2]); ch = rotor(ch,rotors[1],key[1]-ring[1]); ch = rotor(ch,rotors[0],key[0]-ring[0]); // use reflector B ch = simplesub(ch,"YRUHQSLDPXNGOKMIEBFZCWVJAT"); // apply inverse rotor transformations from left to right ch = rotor(ch,rotors[0]+8,key[0]-ring[0]); ch = rotor(ch,rotors[1]+8,key[1]-ring[1]); ch = rotor(ch,rotors[2]+8,key[2]-ring[2]); // apply plugboard transformation again ch = simplesub(ch,plugboard); return ch; } function increment_settings(key,r){ //notch = [['Q','Q'],['E','E'],['V','V'],['J','J'],['Z','Z'],['Z','M'],['Z','M'],['Z','M']]; // The notch array stores the positions at which each rotor kicks over the rotor to its left var notch = [[16,16],[4,4],[21,21],[9,9],[25,25],[25,12],[25,12],[25,12]]; if(key[1] == notch[r[1]][0] || key[1] == notch[r[1]][1]){ key[0] = (key[0]+1)%26; key[1] = (key[1]+1)%26; } if(key[2] == notch[r[2]][0] || key[2] == notch[r[2]][1]){ key[1] = (key[1]+1)%26; } key[2] = (key[2]+1)%26; return key; } // perform a simple substitution cipher function simplesub(ch,key){ return key.charAt(code(ch)); } function rotor(ch,r,offset){ // The first eight strings represent the rotor substitutions I through VIII. The second 8 are the // inverse transformations var key = ["EKMFLGDQVZNTOWYHXUSPAIBRCJ","AJDKSIRUXBLHWTMCQGZNPYFVOE","BDFHJLCPRTXVZNYEIWGAKMUSQO", "ESOVPZJAYQUIRHXLNFTGKDCMWB","VZBRGITYUPSDNHLXAWMJQOFECK","JPGVOUMFYQBENHZRDKASXLICTW", "NZJHGRCXMYSWBOUFAIVLPEKQDT","FKQHTLXOCBJSPDZRAMEWNIUYGV", // inverses "UWYGADFPVZBECKMTHXSLRINQOJ","AJPCZWRLFBDKOTYUQGENHXMIVS","TAGBPCSDQEUFVNZHYIXJWLRKOM", "HZWVARTNLGUPXQCEJMBSKDYOIF","QCYLXWENFTZOSMVJUDKGIARPHB","SKXQLHCNWARVGMEBJPTYFDZUIO", "QMGYVPEDRCWTIANUXFKZOSLHJB","QJINSAYDVKBFRUHMCPLEWZTGXO"]; // the following code looks a bit horrible, but it is essentially just doing a simple substitution // taking into account 16 possible keys (8 rotors and their inverses) and the offset (which is calculated // from the indicator and ring settings). The offset essentially shifts the rotor key to the left or right var chcode = (code(ch)+26+offset)%26; var mapch = (code( key[r].charAt(chcode) ) +26-offset)%26 +65; return String.fromCharCode(mapch); } // return the number 0-25 given a letter [A-Za-z] function code(ch){return ch.toUpperCase().charCodeAt(0) - 65;}