In Latin, “Tabula Prava” means “crooked table.” This is a play on “Tabula Recta” (straight table), which is a grid full of letters used in a number of classic ciphers, including the Vigenère cipher. Tabula Prava is the straightforward combination of a high-entropy key derivation algorithm, which I published earlier on this blog, and the FibonaRNG cipher, also published here. The result is a very secure cipher that is still quite fast and easy to use with pencil and paper.
To encipher something, you need to have a longish key phrase and a Tabula Recta like the one in the picture (after you straighten it, of course). You can make it by hand, but if you feel lazy you can print this file, which contains the Tabula Recta in a gridded 8’5×11 inch sheet. The key phrase should be long so it contains enough entropy. English text has about 1.58 bits of entropy per letter, and since random text contains 4.7 bits of entropy per letter, this means that you need three letters of common text for each letter of random output. We are going to make two mixed alphabets, each of which is characterized by 25 letters (the last letter is forced by the others), so we need a minimum of 150 text letters. Since we also need to provide a seed containing at least three letters so the keystream does not repeat for a message of regular length, the minimum number of letters is 159. I have written a JavaScript program that automates this where the minimum is set at 180 letters; if the text is too short, it repeats until 180 letters are gathered; if too long, it just repeats until the length is a multiple of three.
This is the complete process (as done in the JavaScript program):
- Write the key phrase, minus spaces, diacritic marks, and punctuation, in three rows. For best results, there must be at least 180 letters so that each row contains a minimum of 60 letters. If the text is too short, repeat it until you get 180 letters in three rows of 60. If longer than 160, repeat to the next multiple of 3 and make three rows.
- Combine the letters in each column of the table just formed, using a straight Tabula Recta like the one below, this way: look up the first letter at the top, then go down until the second letter is found, then left or right until the third letter is found, and then finally read the result at the top, and write it down. Examples: H + K = D; H + K + T = Q.
- Convert the first 25 letters of the result into Mixed Alphabet 1 this way: 1, write down new letters in the order they appear; if a letter in the has already been written, write instead the first letter before it in the straight alphabet that is still available (wrap around to the end if needed); 2, then write the last letter still available. Then do the the same with the next 25 letters in order to produce Mixed Alphabet 2. The rest of the letters make up the Seed. Write Mixed Alphabet 1 at the left and right sides of the Tabula Prava, and Mixed Alphabet 2 at the top and bottom.
- If encrypting, write a string of random letters as long as the Seed, which will become the random seed, and then the plaintext (with spaces, punctuation, and diacritics removed) immediately to its right. When decrypting, just write the ciphertext.Then take the Seed and write it at the start of the line below the plaintext.
- If decrypting, extract the random seed from the ciphertext by following the process in step 7 just for those few letters, bearing in mind that you look up the top letters on the left or right of the Tabula Prava, and write into the bottom row the letter found at top or bottom of the table. Skip this step if encrypting.
- Extend the seed (start of the first row if encrypting, of the third row if decrypting) into a keystream so all spaces in the second row are filled, this way: Look up the first keystream letter still available at the top or bottom of the Tabula Prava, then down until you find the letter that follows it in the keystream, then go left to read a letter on the right or left alphabet, which you will write in the next available position below the plaintext. Mark the first keystream letter you looked up so next time you start with the next letter. Notice that when encrypting you start taking letters from the top row, but when you run out of random seed you continue taking them from the second row, never from the plaintext itself.
- When encrypting, do the following for each pair of letters consisting of a plaintext letter and the letter right below it: Look up the plaintext letter at the top or bottom of the Tabula Prava, then go up until you find the letter below, then right to read a letter on the right or left alphabet, which you will write below the pair of letters you involved in this operation, forming the ciphertext. For decryption, do the same but look up the first letter on the left or right instead, and read the result at top or bottom.
I could give you a worked-out example, but it is easier to run the JavaScript program using whatever key phrase and plaintext you want, and look at the intermediate steps and the output. Notice that, since the process differs slightly for encryption and decryption, there is a radio button on the program page to tell it what we want to do. Try doing it by hand as well; the most time-consuming part is likely to be steps 1 to 3, since you will be generating the same high-entropy mixed alphabets even if the actual plaintext is short.
I have covered the security of this algorithm in this other article, so I won’t repeat it here. I will add a couple points that I haven’t covered before:
- You can re-use the key phrase for many messages, so long as you keep coming up with a new random seed in step 4 for each message. This means that you only need to do steps 1 to 3 once when the key phrase changes, and then store the resulting mixed alphabets and seed in a safe place, possibly saving a lot of time. The corresponding areas in the JavaScript program are editable so you can input them directly if necessary (click the buttons next to Encrypt or Decrypt to trigger the rest of the algorithm).
- You will, however, need to generate a different keystream for each message. Otherwise an attacker would be able to obtain the keys from two messages for which the plaintext is known (easier to do than you think). This keystream depends on the random letters that you add in step 4. It is important to make these letters random-looking. Don’t use a word that might be in a dictionary. If you do, you will have to perform the same calculations anyway, and you would have decreased the security of the cipher.
If you follow the steps correctly, you will have a cipher of security comparable to that of the best of today’s computer-based ciphers, but involving a minimum of calculations that can actually be done by hand. This cipher came up as the clear winner in a recent article on high-powered low-tech encryption methods.