The Vigenère cipher dates from the sixteenth century, and resisted deciphering for three centuries. In Part One we look at this ancient cipher, build a data model to represent Vigenère square and use it to display a version in the browser.

A brief history

The Vigenère cipher was first described in 1563 by Giovan Battista Bellaso. It is easy to understand and implement, but resisted attempts to break it until 1863 when Friedrich Kasiski published the first general method for decipering it. In the 19th century the cipher was mistakenly attributed to Blaise de Vigenère, from which it gets ts current name (source:Wikipedia)

How it works

A Caesar cipher consistes of a an alphabet shifted a certain number of places to left or right. Each letter in a message is replaced by its counterpart in the shifted. alphabet. This simple cipher is vulnerable to a frequency analysis, where the number of occurrences of each letter is counted and compared with the known frequency of letters on the source language. This quickly gives a structure to the cipher, from which the meaning can be derived.

The Vigenère cipher uses a table of alphabets, each rotated by one letter, and successive letters are chosen from differetnt rows (and thus rotated by different amounts). The rows used, and the order they are selected depends on a keyword that must be known to both parties. This change in rotation between letters effectively defeats a simple frequency analysis.


  

A Vigenère square

Here we see an example of a Vigenère square. To save space, this example works with just six letters. We can see that the rows in the body of the table are rotated left by one character with respect to the row above.

The code

The Vigenère square is essentiall a two dimensional array, with the keyword letters down the side, and the cipher letters across each row. If we use an associative array in each direction it will make using the table very straightforward. The structure will look like this:

$table = ['A':['A':'A', 'B':'B','C':'C'...],
          'B':['A':'B', 'B':'C','C':'D'...],
          ...]; 

We could just code an array, but that limits the use to the characters we define. It would be more flexible to allow someone using our code to define their own alphabet, so we're going to need some code to create the array from that. We'll also need some code to enchiper and decipher messages, and it would be useful to add a couple of functions to produce some printed versions of the square.

Wrapping this in a class will allow us to encapsulate all the code in a way that doesn't interfere with other scripts. The outline of our class is thus

class Vigenere {

    constructor($alphabet, $keyword) {
    // construct the 2D array here.
    }
    getTextSquare(){
    // return a text representation of the square
    }
    getHTMLSquare(){
    // return a square in HTML that can be formatted with CSS
    }
    encipher(message){
    // Return an enciphered message
    }
    decipher(message) {
    // Decipher and return a message
    }
}

See Part 2 for methods for setting the keyword, and enciphering and deciphering messages.

The constructor

The constructor builds the 2D array we'll use later. Since we're working with arrays we need to split the alphabet string into an array, and create a copy that we can rotate to form the rows.

    // Break alphabet string into an array
    this.alphabet = Array.from(alphabet);

    // Create a copy that we can rotate
    let cipherAlphabet = Array.from(alphabet);

    // Create an empty array to store our square
    this.cipher = [];

    // Loop through the alphabet array creating a row for each letter
    this.alphabet.forEach(el=>{
        // combine the original alphabet as keys with the rotating copy as values
        //this.cipher[el] = this.array_combine(this.alphabet, cipherAlphabet);
            // Rotate the cipher alhpabet
            cipherAlphabet.push(cipherAlphabet.shift());
        });

// this.cipher now contains aour Vigenere square

A helper method

Note the use of a helper method to create the rows, keyed by the original array, and values from the rotated one. This is similar to the PHP array_combine() function, hence the name.

    // Return a new array where the keys are taken from
    // the first array, and the values from the second
    array_combine(a,b) {
        let result = [];
        a.forEach((el,ix)=>{
            result[el] = b[ix];
        });
        return result;
    }

Getting a text square

To create the square we need a heading that we can get from this.alphabet, followed by a series of roes that we get by iterating over this.cipher. We can use Array.join() to combine the arrays into strings and add some whitespace.

    getTextSquare(){
        // Form the top row by joining the original alphabet with some whitespace
        let square = "  | "+this.alphabet.join('  ')+"\n";

        // Create a horizontal line by repeating '---'
        square += "--|"+'---'.repeat(this.alphabet.length)+"\n";

        // Create the body of the square by iterating over the keys and joining the
        // array returned by each key with whitespace
        Object.keys(this.cipher).forEach(el=>{
           square += el + " | "+Object.values(this.cipher[el]).join('  ')+"\n";
        });

        return square;
    }

Getting an HTML square

Returning an HTML square is essntially he same opration as returning a text square, but with a little more text to include the HTML element tags.

      getHTMLsquare(){
        let square = "<table><thead>";
        square += "<tr><td> </td><td>"+this.alphabet.join('</td><td>')+"</td></tr>\n";
        square += "</thead><tbody>";
        Object.keys(this.cipher).forEach(el=>{
            square += `<tr><th>${el}</th><td>` +
                       Object.values(this.cipher[el]).join('</td><td>')+"</td></tr>\n";
        });
        square += "</tbody></table>";
        return square;
    }

The class so far

Put these elements together, and add some code to handle a bad argument passed to the constructor and we get

class Vigenere {

    // Helper method: return a new array where the keys are taken from
    // the first array, and the values from the second
    array_combine(a,b) {
        let result = [];
        a.forEach((el,ix)=>{
            result[el] = b[ix];
        });
        return result;
    }
    /**
    * The constructor
    */
    constructor(alphabet) {
        // Check that we have been provided with a string
        if ((typeof alphabet !== 'string') || alphabet.length === 0) {
            throw "Invalid alphabet - must be a string";
        }
        // Break alphabet string into an array
        this.alphabet = Array.from(alphabet);

        // Create a copy that we can rotate
        let cipherAlphabet = Array.from(alphabet);

        // Create an empty array to store our square
        this.cipher = [];

        // Loop through the alphabet array creating a row for each letter
        this.alphabet.forEach(el=>{
            // combine the original alphabet as keys with the rotating copy as values
            this.cipher[el] = this.array_combine(this.alphabet, cipherAlphabet);
            // Rotate the cipher alphabet
            cipherAlphabet.push(cipherAlphabet.shift());
        });
        // The variable this.cipher now contains our Vigenere square
    }

    /**
     * read the cipher square and return a text representation
     */
    getTextSquare(){
        // Form the top row by joining the original alphabet with some whitespace
        let square = "  | "+this.alphabet.join('  ')+"\n";

        // Create a horizontal line by repeating '---'
        square += "--|"+'---'.repeat(this.alphabet.length)+"\n";

        // Create the body of the square by iterating over the keys and joining the
        // array returned by each key with whitespace
        Object.keys(this.cipher).forEach(el=>{
           square += el + " | "+Object.values(this.cipher[el]).join('  ')+"\n";
        });

        return square;
    }

    /**
     * Read the cipher square and return an HTML version
     */
      getHTMLsquare(){
        let square = "<table><thead>";
        square += "<tr><td> </td><td>"+this.alphabet.join('</td><td>')+"</td></tr>\n";
        square += "</thead><tbody>";
        Object.keys(this.cipher).forEach(el=>{
            square += `<tr><th>${el}</th><td>` +
                       Object.values(this.cipher[el]).join('</td><td>')+"</td></tr>\n";
        });
        square += "</tbody></table>";
        return square;
    }
}

Using the class

Using the class is simply a matter if instantiating it and calling the required methods:

<div id="squareDiv"></div>

<script src="/vigenere.js"></script>
<script>
    let cipher = new Vigenere("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    let square = cipher.getHTMLSquare();
    document.getElementById('squareDiv').innerHTML = square;
</script>

That completes part one of this look at the Vigenère cipher. Check out Part Two for enciphering and deciphering messages, and the completion of our JavaScript class.

Questions or comments?

Contact me!