20 March 2022
Licensed under CC0 1.0 Universal. This document is public domain.
Please email lambdafuzz@tutanota.com with comments, corrections, nice things, etc. Images were made by Science in the Shack.
I have tried my best to make this document accessible to screen readers. I hope I have succeded and the tables I have included prove useful. If not please let me know and I will do my best to fix things.
Words of warning: use at your own risk. Not written by an expert cryptographer. You should find someone who knows what they're doing to confirm this guide's accuracy. No one is liable for anything bad that happens to you because you follow this guide.
To make a perfect OTP, you must adhere to the following principles. Again, it is absolutely imperative or you will not have unbreakable encryption.
1) Each key must be truly randomly generated. Do not use software to generate keys. The deterministic nature of software will only generate pseudo-random numbers that a sophisticated attacker could reproduce and use to break the encryption.
2) The key must be at least as long as the message.
3) Senders and receivers must never reuse keys and they must destroy the keys, random numbers, and messages immediately after sending/decrypting.
Agree on a few conditions ahead of time so there's no confusion when encrypting and decrypting. Obviously there's some leeway here in how you can choose to do things as long as you heed the warnings above. Randomly generated secret keys and modular arithmetic are necessary to ensure the OTP is unbreakable. In this example let's agree that:
1.) Messages can contain both letters and numbers.
2.) Each of these letters and numbers will correspond to values 0 through 35 beginning with A at 0 and 9 at 35 (see Table 2).
3.) We'll use modular addition to encrypt and modular subtraction to decrypt as explained below instead of the other way around.
Use 2 regular 6-sided dice but never ever ever simply add the 2 values together for your numbers because certain values will statistically occur far more often than others and you will introduce bias into things. It’s crucial to make sure each value has the same probability of occurring as any other value. Since we're encrypting both letters and numbers in this example, you will need to assign 36 values starting with 0 to each number/color combination of dice as shown below. If you roll a black 5 and a white 1 for example, you will end up with the random number 24.
The first link below is a table as an image. The second link is a table designed for screen readers. Table links will be presented this way throughout the guide.
Table 1, Image, Unbiased Random Numbers from Two Six-Sided Dice
Table 1, Gemtext for Screen Readers, Unbiased Random Numbers from Two Six-Sided Dice
Let's say we end up with the following random numbers:
2, 16, 3, 2, 5, 30, 32, 17, 22, 8, 11, 13, 11, 35, 26, 14, 31, 1, 6, 19, 4, 4, 33, 5, 11, 8, 6
We'll assign these numbers values between A through Z and 0 through 9 as shown in Table 2 below. Starting at 0 will ensure you don't run into problems with modular arithmetic which we'll get to in a sec.
Table 2, Image, Alphanumeric Mapping to Digits 0 through 35
Table 2, Alphanumeric Mapping to Digits 0 through 35
By assigning letters and numbers to the string of random numbers from our dice rolls, we get the following encryption key:
C Q D C F 4 6 R W I L N L 9 0 O 5 B G T E E 7 F L I G
This will work for a short message. What if we want to send something much longer? Things can get tedious pretty quickly. Maybe there are more efficient ways to generate random numbers (no, I'm absolutely not talking about software!). Can we trust these methods? Better not trust anything. Let's just stick to dice for now.
Share your keys ahead of time (long before you intend to send encrypted messages) with the recipient over some secure channel (probably a face to face meeting). These keys will be used to encrypt and decrypt the messages you'll exchange after your meeting.
If we have a really long stream of random letters and numbers for our key, it's a good idea to start our message with some characters from the key itself before the actual encrypted text so the recipient will know where in the key they should start decrypting. Let's use the first five characters we generated (although in a longer example you might want to use a longer sequence to reduce the likelihood that there are identical sequences in the key somewhere however unlikely).
Our first five values were CQDCF. If I'm receiving this message from you, I'll find those characters in my key and then start with the first character after that to decrypt.
Let's say you want to send the message "YOU NEED TO MOVE BEFORE 830" to your recipient. Write out the plaintext and the key below it for convenience:
Plaintext:
Y O U N E E D T O M O V E B E F O R E 8 3 0
Key:
4 6 R W I L N L 9 0 O 5 B G T E E 7 F L I G
To encrypt the message and generate the ciphertext (the encrypted message that’s safe to send over any insecure channel), we'll use modular addition which reveals nothing about the values added together. Think of modular addition like you would think of moving around a clock: if we start at 9pm, adding 8 hours puts us at 5am. With this OTP of letters and numbers, we need to use modulo 36 as if we had a 36 hour clock starting at 0 (0 to 35). If we were only encrypting digits, we would use modulo 10. If we were only encrypting English letters we would use modulo 26 and so on.
The modular addition process goes like this: start with “Y” in the plaintext which corresponds to the value 24 in Table 2. Look up the first character in the key, “4”, in Table 2 which has a value of 30. Add these values together (24+30) as if you're going around our 0 to 35 hour clock. Start at 24, move clockwise around the circle and pass 0, and land on the value 18 which corresponds to “S” in Table 2. “S” then becomes the first letter of the encrypted ciphertext.
Thus our ciphertext would be:
S K B 9 M P Q 4 N C 2 Q F H X J S O J J B 6
Alternatively you could use a tabula recta (Table 3 and Table 4) to speed up the process. It’s important to understand the modular arithmetic in case you don't have access to a tabula recta or can’t remember how to encrypt/decrypt with one. To decrypt the message, work backward and use modular subtraction (going counterclockwise around our imaginary 0 to 35 clock) to subtract the key from the ciphertext and yield the plaintext. This means you start with “S” from the ciphertext and find that it has a value of 18 in Table 2. Then subtract 30, which is the value of “4” from the key according to Table 2, to get a value of 24. This value corresponds to “Y” in Table 2 and is the first letter of the plaintext.
To encrypt start with the plaintext character in its row and find the point where it meets the column of the key character. Starting with plaintext “Y” and key “4” this way should give you ciphertext “S”. Use pieces of paper to help guide your eyes.
Table 3, Image, Alphanumeric Tabula Recta Outcomes When Encrypting
Table 3, Alphanumeric Tabula Recta Outcomes When Encrypting
To decrypt start with the row of the letter from your key and move over to the ciphertext letter in that row. Your plaintext letter will be at the top of the column you’re in. Starting with key “9” and ciphtertext “N” sould give you “O” (oh, not zero).
Table 4, Image, Alphanumeric Tabula Recta Outcomes When Decrypting
Table 4, Alphanumeric Tabula Recta Outcomes When Decrypting
This is all assuming that you’re using modular addition to encrypt and modular subtraction to decrypt.
Destroy your plaintext, key, and the random numbers used to generate it. This step is absolutely necessary. Make sure the recipient understands to do the same after decrypting. Threaten them.
Assuming the keys have never been compromised and you did everything perfectly you can now send the encrypted message over any insecure channel. Post it on Facebook! No, you wouldn't be caught dead on there. That's good. I mean, you could send the message this way and it would still be safe but don't use Facebook because Facebook uses you.
The message has now been transmitted and all attackers have been thwarted!
Since I love Haskell I decided to write some to generate all the tables for screen readers that would have been tedious to create by hand. As a bonus I'll link to that file below as gemtext and plain Haskell so you can make it your own if you want to.
Haskell File as Gemtext to Output Table Text for Screen Readers