literate_crypto/cipher/block/modes/
ecb.rs

1use {
2    crate::{
3        BlockCipher,
4        BlockDecrypt,
5        BlockEncrypt,
6        BlockMode,
7        Cipher,
8        CipherDecrypt,
9        CipherEncrypt,
10        Padding,
11    },
12    std::{convert::Infallible, fmt},
13};
14
15/// Electronic codebook mode, a simple and insecure [mode of
16/// operation](crate::BlockMode).
17///
18/// ECB is the simplest mode of operation for block ciphers: it simply splits
19/// the input data into blocks, and encrypts each block independently.
20///
21/// # Security
22///
23/// ECB is insecure because the same block in the plaintext will always encrypt
24/// to the same block in the ciphertext. Imagine a server accepting encrypted
25/// YES/NO messages from a client. If an attacker can see the encrypted
26/// messages, he will know when the client is sending two identical messages. If
27/// the attacker can perform some context-dependent analysis of the messages, he
28/// might even be able to guess which messages are being sent (YES or NO).
29#[derive(Debug)]
30pub struct Ecb<Cip, Pad> {
31    cip: Cip,
32    pad: Pad,
33}
34
35impl<Cip: BlockCipher, Pad: Padding> Ecb<Cip, Pad> {
36    pub fn new(cip: Cip, pad: Pad) -> Self {
37        Self { cip, pad }
38    }
39}
40
41impl<Cip: BlockCipher, Pad: Padding> Cipher for Ecb<Cip, Pad>
42where
43    Cip::Block: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug> + AsRef<[u8]>,
44    Cip::Key: Clone,
45{
46    type Key = Cip::Key;
47}
48
49impl<Cip: BlockCipher, Pad: Padding> BlockMode for Ecb<Cip, Pad>
50where
51    Cip::Block: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug> + AsRef<[u8]>,
52    Cip::Key: Clone,
53{
54}
55
56impl<Enc: BlockEncrypt, Pad: Padding> CipherEncrypt for Ecb<Enc, Pad>
57where
58    Enc::EncryptionBlock: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug> + AsRef<[u8]>,
59    Enc::EncryptionKey: Clone,
60{
61    type EncryptionErr = Infallible;
62    type EncryptionKey = Enc::EncryptionKey;
63
64    fn encrypt(
65        &self,
66        data: Vec<u8>,
67        key: Self::EncryptionKey,
68    ) -> Result<Vec<u8>, Self::EncryptionErr> {
69        // Encrypt the blocks in-place, using the input vector.
70        let block_size = std::mem::size_of::<Enc::EncryptionBlock>();
71        let mut data = self.pad.pad(data, block_size);
72        for chunk in data.chunks_mut(block_size) {
73            let block = chunk.try_into().unwrap();
74            chunk.copy_from_slice(self.cip.encrypt(block, key.clone()).as_ref());
75        }
76        Ok(data)
77    }
78}
79
80impl<Dec: BlockDecrypt, Pad: Padding> CipherDecrypt for Ecb<Dec, Pad>
81where
82    Dec::DecryptionBlock: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug> + AsRef<[u8]>,
83    Dec::DecryptionKey: Clone,
84{
85    type DecryptionErr = Pad::Err;
86    type DecryptionKey = Dec::DecryptionKey;
87
88    fn decrypt(
89        &self,
90        mut data: Vec<u8>,
91        key: Self::DecryptionKey,
92    ) -> Result<Vec<u8>, Self::DecryptionErr> {
93        // Decrypt the blocks in-place, using the input vector.
94        let block_size = std::mem::size_of::<Dec::DecryptionBlock>();
95        for chunk in data.chunks_mut(block_size) {
96            let block = chunk.try_into().unwrap();
97            chunk.copy_from_slice(self.cip.decrypt(block, key.clone()).as_ref());
98        }
99        self.pad.unpad(data, block_size)
100    }
101}