23
Intro to the One-Time Pad Cipher
The post Intro to the One-Time Pad Cipher first appeared on Qvault.
In cryptography, the one-time pad, or OTP is a way of encrypting information so securely that it’s impossible to be cracked. That said, OTP has a major drawback in that it requires both parties to have access to the same key before a message is encrypted.
When using the one-time pad, a message and a secret key are required to start. Each bit of the original messageg, assuming we can use binary data, is encrypted by using an XOR
operation on it and the corresponding bit from the secret key.
XOR, or “exclusive or” is a binary operator that works with binary data. It returns true
if both of its inputs are opposites (one false and one true), otherwise, it returns false
.
true XOR false = true
false XOR true = true
true XOR true = false
false XOR false = false
<small id="shcb-language-1"><span>Code language:</span> <span>PHP</span> <span>(</span><span>php</span><span>)</span></small>
Check out my other article, why exclusive or is important in cryptography, if you want more information.
So, for example, if we start with the message “hello word” and the key “I not know”, first we’d covert the text to binary data.
hello world = 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01100100
I not know = 01001001 00100000 01101110 01101111 01110100 00100000 01101011 01101110 01101111 01110111
Next, we’ll perform the XOR
operation on all the data.
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01100100
XOR
01001001 00100000 01101110 01101111 01110100 00100000 01101011 01101110 01101111 01110111
=
00100001 01000101 00000010 00000011 00011011 00000000 00011100 00000001 00011101 00010011
<small id="shcb-language-2"><span>Code language:</span> <span>PHP</span> <span>(</span><span>php</span><span>)</span></small>
The resulting binary data is now the “cipher text”. In order to convert it back, all we need to do is XOR
the ciphertext with the key and we’ll get the original message back.
00100001 01000101 00000010 00000011 00011011 00000000 00011100 00000001 00011101 00010011
XOR
01001001 00100000 01101110 01101111 01110100 00100000 01101011 01101110 01101111 01110111
=
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01100100
<small id="shcb-language-3"><span>Code language:</span> <span>PHP</span> <span>(</span><span>php</span><span>)</span></small>
Convert the result back to text and we have the original message decrypted.
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01100100
=
hello world
A cipher is said to have perfect security if an attacker who has access to only the ciphertext can infer absolutely nothing of interest about the plaintext. The one-time pad does have perfect security. That said, it only has perfect security if the following conditions can be met:
- The key must be at least as long as the plaintext
- The key must never be reused
- The key must be kept completely secret to the outside world yet shared by both parties
- The key must have a uniform distribution that is independent of the plaintext
The Caesar cipher is a great example of a cipher that is not perfectly secure or practically secure. As we demonstrated earlier, when given access to the ciphertext of a Caesar cipher, an attacker can see the positions and patterns of characters in the plaintext.
Most production ciphers are not perfectly secure, but are “close enough”. In short, trade-offs are made that add to the practical security of a system while sacrificing the perfect theoretical security of the cipher itself.
In accordance with the requirements outlined above, it’s really hard to implement a secure one-time pad in a real-world system. Let’s look at the first requirement, that the key needs to be at least as long as the plaintext it encrypts. This means that if I want to encrypt the contents of my computer’s hard drive, I need a key that’s hundreds of gigabytes in length. There’s no way I’ll remember that key, let alone be able to write it down.
The second requirement, that the key can’t be reused, is a huge pain! This means memorizing keys is out of the question because I always need a new one. Not only that, but whatever security vulnerabilities are introduced by needing to communicate a shared key to my intended recipient will be repeated each time a new message is sent.
Lastly, the last requirement, that it must be kept secret yet somehow communicated to the intended recipient, is a tall order. In fact, all symmetric encryption algorithms suffer from this problem. As a result, if you need to communicate with another entity you probably need to use a separate asymmetric encryption scheme.
func encrypt(plaintext, key []byte) []byte {
final := []byte{}
for i := range plaintext {
final = append(final, plaintext[i]^key[i])
}
return final
}
func decrypt(ciphertext, key []byte) []byte {
final := []byte{}
for i := range ciphertext {
final = append(final, ciphertext[i]^key[i])
}
return final
}
<small id="shcb-language-4"><span>Code language:</span> <span>Go</span> <span>(</span><span>go</span><span>)</span></small>
Ready to get coding?
Follow and hit me up on Twitter @q_vault if you have any questions or comments. If I’ve made a mistake in the article be sure to let me know so I can get it corrected!
23