The Nihilist Cipher

Nihilists in The Big Lebowski
Ja, it seems you have forgotten our little deal, Lebowski

It may be easiest to just let Wikipedia explain the background of the Nihilist Cipher:

In the history of cryptography, the Nihilist cipher is a manually operated symmetric encryption cipher originally used by Russian Nihilists in the 1880s to organize terrorism against the tsarist regime.

There are three parts to this cipher:

  • The keyword used to create a polybius square
  • The key to encrypt the plaintext
  • The plaintext to encrypt


The first step is to create the polybius square. The square was invented by ancient Greek historian and scholar Polybius as a method of fractionating text. A standard polybius square would look something like this:

1 2 3 4 5
1 A B C D E
2 F G H I/J K
3 L M N O P
4 Q R S T U
5 V W X Y Z

Frequently I/J or C/K are combined in order to make it a 5×5 square. A 6×6 square could also be built, utilizing the complete alphabet and the digits 0-9. If you wanted to encode the word “KREMLIN” you just look up each letter in the table. “K” would be row 2, column 5, so it becomes “25”. The entire word would be “25 42 15 32 31 24 33”. To increase the security of the message encoded, the Nihilist Cipher uses a keyword based polybius square. A secret word, “BISHOP” in this example, is appended at the start of the alphabet, and then all remaining letters are listed in alphabetical order:

1 2 3 4 5
1 B I S H O
2 P A C D E
3 F G K L M
4 N Q R T U
5 V W X Y Z

With this new table, “KREMLIN” now becomes “33 43 25 35 34 12 41”.

The second part of the Nihilist Cipher is the key, which is used to encrypt the plaintext message. It is run through the polybius square as well. If it is shorter than the message it is extended through repetition. The numbers for the encoded plaintext are added to those for the encoded key and the final ciphertext is the result.

For the message “No, It’s THE code breaker. No more secrets”, a keyword of “BISHOP”, and a key of “TRON”, here is how it would work. First we create a compressed version of the message and extend the key so that it’s the same length as the message:

  • Compressed message: NOITSTHECODEBREAKERNOMORESECRETS
  • Extended key: TRONTRONTRONTRONTRONTRONTRONTRON

Then both are encoded using the “BISHOP” based polybius square above, which results in:

  41 15 12 44 13 44 14 25 23 15 24 25 11 43 25 22 33 25 43 41 15 35 15 43 25 13 25 23 43 25 44 13
+ 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41
= 85 58 27 85 57 87 29 66 67 58 39 66 55 86 40 63 77 68 58 82 59 78 30 84 69 56 40 64 87 68 59 54

The final row is the ciphertext which can be passed on in a more secure fashion. Decrypting the message is done by reversing the process: subtracting the key from the ciphertext and then running it through the polybius square.

  85 58 27 85 57 87 29 66 67 58 39 66 55 86 40 63 77 68 58 82 59 78 30 84 69 56 40 64 87 68 59 54
- 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41 44 43 15 41
= 41 15 12 44 13 44 14 25 23 15 24 25 11 43 25 22 33 25 43 41 15 35 15 43 25 13 25 23 43 25 44 13

An example of the Nihilist Cipher in Javascript:


var letters = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
// encrypt and decrypt this plain text
var plainText = "No Its THE code breaker No more secrets";
// remove spaces
var compressedText = plainText.replace(/\s+/g, "").toLocaleUpperCase();
var decryptedText = "";
// The key needs to be repeated until it's the same length as the text to encrypt
var key = "TRON";
var extendedKey = extendKey(key, compressedText.length);
// Two options for a polybius square
// polybius square – 5×5 = 25 letters. combine I/J
// polybuis square – 6×6 = 26 letters + 0-9 digits
// Keyword for square cannot have repetitive letters
// or can, but must be filtered out, which this code does
var keyword = "BISHOP";
var polybiusLetters = keyword + letters;
var polybiusLetters = polybiusLetters.split('').filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
var polybiusSquare = [[]];
var index = 0;
for (var i = 0; i<5; i++) {
polybiusSquare[i] = [];
for (var j = 0; j<5; j++) {
var letter = polybiusLetters[index];
polybiusSquare[i][j] = letter;
index++;
}
}
var compTextArray = buildArray(compressedText, polybiusSquare);
var extKeyArray = buildArray(extendedKey, polybiusSquare);
var cipherArray = [];
// create the ciphertext by adding the plaintext and key together
for (var i = 0; i<compTextArray.length; i++) {
cipherArray.push(compTextArray[i] + extKeyArray[i]);
}
var decryptArray = []
// we're simply reversing the above process to decrypt
for (var i = 0; i<cipherArray.length; i++) {
decryptArray.push(cipherArray[i] – extKeyArray[i]);
}
// rebuild the original message by looking up letters in the square
for (var i = 0; i < decryptArray.length; i++) {
decryptedText += lookupLetter(decryptArray[i], polybiusSquare);
}
// Let's see if it worked
console.log("compressedText", compressedText);
console.log("decryptedText ", decryptedText);
// Lookup letters in the square
function lookupLetter(chunk, polybiusSquare) {
var coords = String(chunk).split("");
var row = Number(coords[0]);
var col = Number(coords[1]);
// the row and col values have been increased by 1 to match the 1-5 values
// of a written polybius square. decrease by 1
row–;
col–;
return polybiusSquare[row][col];
}
function buildArray(letters, polybiusSquare) {
var returnArray = [];
for (var i = 0; i<letters.length; i++) {
var char = letters[i];
returnArray.push(findChunk(char, polybiusSquare))
}
return returnArray;
}
// find a letter in the square
function findChunk(findMe, polybiusSquare) {
for (var i = 0; i<5; i++) {
for (var j = 0; j<5; j++) {
if (polybiusSquare[i][j] === findMe) {
// the Polybius square has rows and columns labeled 1,2,3,4,5
// so increment the row and column for display
i++;
j++;
return Number("" + i + j); // this is hacky, but it works
}
}
}
}
// extend the key to a predetermined length
function extendKey(key, length) {
var longKey = key;
while (longKey.length < length) {
longKey += key;
}
return longKey.substring(0, length);
}

view raw

nihilist.js

hosted with ❤ by GitHub

This entry was posted in Ciphers, Crypto and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *