Skip to content

Instantly share code, notes, and snippets.

@ccckmit
Last active August 29, 2015 14:16
Show Gist options
  • Save ccckmit/b0a90a7bd9d3d3e5baa8 to your computer and use it in GitHub Desktop.
Save ccckmit/b0a90a7bd9d3d3e5baa8 to your computer and use it in GitHub Desktop.

Revisions

  1. ccckmit renamed this gist Mar 2, 2015. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. ccckmit created this gist Mar 2, 2015.
    122 changes: 122 additions & 0 deletions gistfile1.txt
    Original 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;}