A polyalphabetic substitution cipher invented by Blaise de Vigenère in the 1500's. It has N different cipher alphabets, where N is the number of letters in the alphabet, each shifted by one letter with respect to the previous alphabet. A grid is drawn NxN. The first row is a cipher alphabet with a Caesar shift of one. The second has a Caesar shift of two and so on.

Next a key is selected. The letters of the key define which rows to use and in what order. So when encrypting plaintext the first letter of the plaintext is encrypted using the cipher alphabet specified by the first letter of the key (the row that starts with the first letter of the key). The second letter of the plaintext is encrypted using the row that starts with the second letter of the key and so on until you have used every letter in the key then you start over at the beginning of the key.

For many years it was believed that this cipher was unbreakable. Then in the 1800's, sometime prior to 1854, Charles Babbage managed to tackle the beast. Yet since he never published his findings it wouldn't be until 1863 before the world would know the square was breakable. In 1863 Friedrich Kasiski independently discovered the same technique Babbage found. (see Breaking the Vigenère cipher)

This square can be used as the basis for a One-time Pad. The difference is that the key of a One-time Pad has a length of at least the plaintext, so there is no repetition, and the letters that make up the key are generated at random to avoid any unintended repetition. By using a key this long that doesn't contain repetition it isn't susceptible to the codebreaking technique developed by Babbage and Kasiski.

The Vigenère Square for English:

         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

     B   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 A 
     C   C D E F G H I J K L M N O P Q R S T U V W X Y Z A B
     D   D E F G H I J K L M N O P Q R S T U V W X Y Z A B C 
     E   E F G H I J K L M N O P Q R S T U V W X Y Z A B C D 
     F   F G H I J K L M N O P Q R S T U V W X Y Z A B C D E 
     G   G H I J K L M N O P Q R S T U V W X Y Z A B C D E F 
     H   H I J K L M N O P Q R S T U V W X Y Z A B C D E F G 
     I   I J K L M N O P Q R S T U V W X Y Z A B C D E F G H 
     J   J K L M N O P Q R S T U V W X Y Z A B C D E F G H I 
     K   K L M N O P Q R S T U V W X Y Z A B C D E F G H I J 
     L   L M N O P Q R S T U V W X Y Z A B C D E F G H I J K 
     M   M N O P Q R S T U V W X Y Z A B C D E F G H I J K L 
     N   N O P Q R S T U V W X Y Z A B C D E F G H I J K L M 
     O   O P Q R S T U V W X Y Z A B C D E F G H I J K L M N 
     P   P Q R S T U V W X Y Z A B C D E F G H I J K L M N O 
     Q   Q R S T U V W X Y Z A B C D E F G H I J K L M N O P 
     R   R S T U V W X Y Z A B C D E F G H I J K L M N O P Q 
     S   S T U V W X Y Z A B C D E F G H I J K L M N O P Q R
     T   T U V W X Y Z A B C D E F G H I J K L M N O P Q R S 
     U   U V W X Y Z A B C D E F G H I J K L M N O P Q R S T 
     V   V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
     W   W X Y Z A B C D E F G H I J K L M N O P Q R S T U V
     X   X Y Z A B C D E F G H I J K L M N O P Q R S T U V W
     Y   Y Z A B C D E F G H I J K L M N O P Q R S T U V W X 
     Z   Z 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
     A   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

A Vigenère square in javascript

This is is a javascript version of the Vigenère cipher. It uses the characters that can be found on a US keyboard as it's alphabet. I can't guarantee it to be bug free, but it encrypted and decrypted itself successfully. It keeps case and can handle numbers and special chars. Almost anything you can type with your keyboard. If it can't encode a char it should just pass through without interrupting the encrypting of the rest of the message. All tabs (\t and \v) and newlines (\f, \n, and \r) are trimmed out and replaced with a single space. I've tried to make this as usable in the real world as possible.

To see it in action go to http://www.babelfeesh.com/crypto/vigenere.html.

Thank wharfinger for the e2 source code formatter. And for more info see Breaking the Vigenère cipher and One-Time Pad.

Cryptology Meta-Node


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<title>Vigenère Square in Javascript</title>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">

// produce our cipher alphabet for vigenere square
var soup = new Array();
var cnt=0;
soup[cnt++] = " ";
soup[cnt++] = "a";
soup[cnt++] = "b";
soup[cnt++] = "c";
soup[cnt++] = "d";
soup[cnt++] = "e";
soup[cnt++] = "f";
soup[cnt++] = "g";
soup[cnt++] = "h";
soup[cnt++] = "i";
soup[cnt++] = "j";
soup[cnt++] = "k";
soup[cnt++] = "l";
soup[cnt++] = "m";
soup[cnt++] = "n";
soup[cnt++] = "o";
soup[cnt++] = "p";
soup[cnt++] = "q";
soup[cnt++] = "r";
soup[cnt++] = "s";
soup[cnt++] = "t";
soup[cnt++] = "u";
soup[cnt++] = "v";
soup[cnt++] = "w";
soup[cnt++] = "x";
soup[cnt++] = "y";
soup[cnt++] = "z";
soup[cnt++] = "A";
soup[cnt++] = "B";
soup[cnt++] = "C";
soup[cnt++] = "D";
soup[cnt++] = "E";
soup[cnt++] = "F";
soup[cnt++] = "G";
soup[cnt++] = "H";
soup[cnt++] = "I";
soup[cnt++] = "J";
soup[cnt++] = "K";
soup[cnt++] = "L";
soup[cnt++] = "M";
soup[cnt++] = "N";
soup[cnt++] = "O";
soup[cnt++] = "P";
soup[cnt++] = "Q";
soup[cnt++] = "R";
soup[cnt++] = "S";
soup[cnt++] = "T";
soup[cnt++] = "U";
soup[cnt++] = "V";
soup[cnt++] = "W";
soup[cnt++] = "X";
soup[cnt++] = "Y";
soup[cnt++] = "Z";
soup[cnt++] = "`";
soup[cnt++] = "1";
soup[cnt++] = "2";
soup[cnt++] = "3";
soup[cnt++] = "4";
soup[cnt++] = "5";
soup[cnt++] = "6";
soup[cnt++] = "7";
soup[cnt++] = "8";
soup[cnt++] = "9";
soup[cnt++] = "0";
soup[cnt++] = "-";
soup[cnt++] = "=";
soup[cnt++] = "[";
soup[cnt++] = "]";
soup[cnt++] = "\\";
soup[cnt++] = ";";
soup[cnt++] = "'";
soup[cnt++] = ",";
soup[cnt++] = ".";
soup[cnt++] = "/";
soup[cnt++] = "~";
soup[cnt++] = "!";
soup[cnt++] = "@";
soup[cnt++] = "#";
soup[cnt++] = "$";
soup[cnt++] = "%";
soup[cnt++] = "^";
soup[cnt++] = "&";
soup[cnt++] = "*";
soup[cnt++] = "(";
soup[cnt++] = ")";
soup[cnt++] = "_";
soup[cnt++] = "+";
soup[cnt++] = "{";
soup[cnt++] = "}";
soup[cnt++] = "|";
soup[cnt++] = ":";
soup[cnt++] = "\"";
soup[cnt++] = "<";
soup[cnt++] = ">";
soup[cnt++] = "?";

// setup the vigenere square
var encvigsq = new Array();
for (var vi=0; vi < soup.length; vi++) {
    encvigsq[soup[vi]] = new Array();
    for (var vj=0; vj < soup.length; vj++) {
        var letter = vi+vj;
        if (vi+vj > (soup.length - 1)) {
            letter = vi+vj-soup.length;
        }
        encvigsq[soup[vi]][soup[vj]] = soup[letter];
    }
}

// setup an array for decoding the vigenere square
var decvigsq = new Array();
for (var di=0; di < soup.length; di++) {
    decvigsq[soup[di]] = new Array();
    for(var dj=0; dj < soup.length; dj++) {
        decvigsq[soup[di]][encvigsq[soup[di]][soup[dj]]] = soup[dj];
    }
}

/*///////////////////////// encode using the vigenere square ///////////////////*/

function encodevig() {
    // comments 
    var sourceString = document.getElementById("source").value;
    sourceString = sourceString.replace(/[\t\f\n\r\v]+/g, " ");
    var outputString = "";
    var keyString = document.getElementById("vigkey").value;
    keyString = keyString.replace(/[\t\f\n\r\v]+/g, " ");
    var keyidx = 0;
    for (var i = 0; i < sourceString.length; i++) {
        if (encvigsq[keyString.charAt(keyidx)][sourceString.charAt(i)] != null) {
            outputString += encvigsq[keyString.charAt(keyidx)][sourceString.charAt(i)];
            if (keyidx == (keyString.length - 1)) {
                keyidx = 0;
            } else {
                keyidx++;
            }
        } else {
            outputString += sourceString.charAt(i);
        }
    }
    document.getElementById("destination").value = outputString;
}

/*///////////////////////// decode using the vigenere square ///////////////////*/

function decodevig() {
    // comments 
    var sourceString = document.getElementById("source").value;
    sourceString = sourceString.replace(/[\t\f\n\r]+/g, " ");
    var outputString = "";
    var keyString = document.getElementById("vigkey").value;
    keyString = keyString.replace(/[\t\f\n\r\v]+/g, " ");
    var keyidx = 0;
    for (var i = 0; i < sourceString.length; i++){
        if (decvigsq[keyString.charAt(keyidx)][sourceString.charAt(i)]) {
            outputString += decvigsq[keyString.charAt(keyidx)][sourceString.charAt(i)];
            if (keyidx == (keyString.length - 1)) {
                keyidx = 0;
            } else {
                keyidx++;
            }
        } else {
            outputString += sourceString.charAt(i);
        }
    }
    document.getElementById("destination").value = outputString;
}


</script>
</head>

<body>
<h1 align="center">A Vigenère Square in Javascript</h1>
Note: I've used a larger alphabet than most implementations I've found.
It keeps case and can handle numbers and special chars.  Almost anything you
can type with your keyboard.  If it can't encode a char it should just pass
through without interrupting the encrypting of the rest of the message. All
tabs (\t and \v) and newlines (\f, \n, and \r) are trimmed out and replaced
with a single space.
<p>
Disclaimer: I don't promise this to be bug free. It is also a well known
algorithm and is not difficult to crack.  Do not use for actual secure
communications.  But if it is bug free it can be used as a One Time Pad which is very secure.
<p>
<textarea id="source" cols=70 rows=10></textarea><br />
<button id="dovig" onclick="encodevig()">Encode (Vigenere Sq)</button>
<button id="undovig" onclick="decodevig()">Decode (Vigenere Sq)</button>
<b>Key:</b> <input id="vigkey" size="20" value="default">
<br />
<textarea id="destination" cols=70 rows=10></textarea>
</body>
</html>