literate_crypto/cipher/
onetimepad.rs

1use {
2    crate::{BlockMode, Cipher, CipherDecrypt, CipherEncrypt},
3    docext::docext,
4    std::{fmt, marker::PhantomData},
5};
6
7/// The one-time pad is a simple cipher which XORs the input plaintext with the
8/// key.
9///
10/// This means that the key must be at least as long as the plaintext. The
11/// key determines which bits of the plaintext will be flipped: if a bit in the
12/// key is 1, then the corresponding bit of plaintext will be flipped when
13/// generating the plaintext. For this reason, the key should be uniformly
14/// random and free of any patterns that can be analyzed.
15///
16/// Because the XOR operation cancels itself ($X \oplus Y \oplus Y = X$ for any
17/// $X, Y$), the decryption process is exactly the same as encryption.
18///
19/// If the key is kept secret and uniformly random, the one-time pad can be
20/// mathematically proven to be a perfect cipher, meaning that the ciphertext
21/// reveals absolutely nothing about the plaintext.
22#[docext]
23#[derive(Debug)]
24pub struct OneTimePad<K>(PhantomData<K>);
25
26impl<K> Default for OneTimePad<K> {
27    fn default() -> Self {
28        Self(Default::default())
29    }
30}
31
32impl<K: Iterator<Item = u8>> Cipher for OneTimePad<K> {
33    type Key = K;
34}
35
36impl<K: Iterator<Item = u8>> BlockMode for OneTimePad<K> {}
37
38impl<K: Iterator<Item = u8>> CipherEncrypt for OneTimePad<K> {
39    type EncryptionErr = KeyTooShort;
40    type EncryptionKey = K;
41
42    fn encrypt(
43        &self,
44        data: Vec<u8>,
45        key: Self::EncryptionKey,
46    ) -> Result<Vec<u8>, Self::EncryptionErr> {
47        cipher(data, key)
48    }
49}
50
51impl<K: Iterator<Item = u8>> CipherDecrypt for OneTimePad<K> {
52    type DecryptionErr = KeyTooShort;
53    type DecryptionKey = K;
54
55    fn decrypt(
56        &self,
57        data: Vec<u8>,
58        key: Self::DecryptionKey,
59    ) -> Result<Vec<u8>, Self::DecryptionErr> {
60        // Because XOR is symmetric, the decryption process is equivalent to
61        // encryption.
62        cipher(data, key)
63    }
64}
65
66fn cipher(mut data: Vec<u8>, mut key: impl Iterator<Item = u8>) -> Result<Vec<u8>, KeyTooShort> {
67    for x in data.iter_mut() {
68        *x ^= key.next().ok_or(KeyTooShort)?;
69    }
70    Ok(data)
71}
72
73#[derive(Debug)]
74pub struct KeyTooShort;
75
76impl fmt::Display for KeyTooShort {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        f.write_str("key is too short for one-time pad input")
79    }
80}