literate_crypto/cipher/block/modes/
cbc.rs

1use {
2    crate::{
3        BlockCipher,
4        BlockDecrypt,
5        BlockEncrypt,
6        BlockMode,
7        Cipher,
8        CipherDecrypt,
9        CipherEncrypt,
10        Padding,
11    },
12    docext::docext,
13    std::{convert::Infallible, fmt, mem::size_of},
14};
15
16/// Cipher block chaining mode is the most common [mode of
17/// operation](crate::BlockMode) for block ciphers which combines every block
18/// with all of the previous blocks of ciphertext.
19///
20/// Given a block cipher $E_k$ with key $k$ and some plaintext $P = P_1
21/// \parallel P_2 \parallel \dots \parallel P_n$, where $P_i$ are the plaintext
22/// blocks, CBC mode encrypts $P$ as follows:
23///
24/// $$
25/// C_i = E(P_i \oplus C_{i-1}),\\
26/// C = C_1 \parallel C_2 \parallel \dots \parallel C_n
27/// $$
28///
29/// $C_0$ is a special value called the _initialization vector (IV)_.
30///
31/// In other words, CBC XORs the plaintext of each block with the ciphertext of
32/// the previous block before encrypting it. This means that each block depends
33/// on all blocks before it, and changing a single bit in the plaintext will
34/// cause every next block of ciphertext to change in an unpredictable way.
35///
36/// # IV
37///
38/// The first block of plaintext is XORed with an initialization vector (IV),
39/// referred to as $C_0$ above. The IV is a block of random data which does not
40/// need to be secret, but it must be unique for each message encrypted with the
41/// same key. The IV is necessary in order to decrypt the ciphertext, and must
42/// be sent to the recipient along with the ciphertext.
43///
44/// Because the same plaintext with a different IV will encrypt to a different
45/// ciphertext, CBC solves the issues of [ECB mode](crate::Ecb#security).
46#[docext]
47pub struct Cbc<Cip, Pad, Block> {
48    cip: Cip,
49    pad: Pad,
50    iv: Block,
51}
52
53impl<Cip, Pad, Block> Cbc<Cip, Pad, Block> {
54    pub fn new(cip: Cip, pad: Pad, iv: Block) -> Self {
55        Self { cip, pad, iv }
56    }
57}
58
59impl<Cip: BlockCipher, Pad: Padding> Cipher for Cbc<Cip, Pad, Cip::Block>
60where
61    Cip::Block: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
62        + AsRef<[u8]>
63        + AsMut<[u8]>
64        + IntoIterator<Item = u8>
65        + Clone,
66    Cip::Key: Clone,
67{
68    type Key = Cip::Key;
69}
70
71impl<Cip: BlockCipher, Pad: Padding> BlockMode for Cbc<Cip, Pad, Cip::Block>
72where
73    Cip::Block: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
74        + AsRef<[u8]>
75        + AsMut<[u8]>
76        + IntoIterator<Item = u8>
77        + Clone,
78    Cip::Key: Clone,
79{
80}
81
82impl<Enc: BlockEncrypt, Pad: Padding> CipherEncrypt for Cbc<Enc, Pad, Enc::EncryptionBlock>
83where
84    Enc::EncryptionBlock: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
85        + AsRef<[u8]>
86        + AsMut<[u8]>
87        + IntoIterator<Item = u8>
88        + Clone,
89    Enc::EncryptionKey: Clone,
90{
91    type EncryptionErr = Infallible;
92    type EncryptionKey = Enc::EncryptionKey;
93
94    fn encrypt(
95        &self,
96        data: Vec<u8>,
97        key: Self::EncryptionKey,
98    ) -> Result<Vec<u8>, Self::EncryptionErr> {
99        let block_size = size_of::<Enc::EncryptionBlock>();
100        let mut prev = self.iv.clone();
101        let mut data = self.pad.pad(data, block_size);
102        // Encrypt the blocks in-place, using the input vector.
103        for chunk in data.chunks_mut(block_size) {
104            let mut block: Enc::EncryptionBlock = chunk.try_into().unwrap();
105            block
106                .as_mut()
107                .iter_mut()
108                .zip(prev.into_iter())
109                .for_each(|(a, b)| *a ^= b);
110            let ciphertext = self.cip.encrypt(block, key.clone());
111            chunk.copy_from_slice(ciphertext.as_ref());
112            prev = ciphertext;
113        }
114        Ok(data)
115    }
116}
117
118impl<Dec: BlockDecrypt, Pad: Padding> CipherDecrypt for Cbc<Dec, Pad, Dec::DecryptionBlock>
119where
120    Dec::DecryptionBlock: for<'a> TryFrom<&'a mut [u8], Error: fmt::Debug>
121        + AsRef<[u8]>
122        + AsMut<[u8]>
123        + IntoIterator<Item = u8>
124        + Clone,
125    Dec::DecryptionKey: Clone,
126{
127    type DecryptionErr = Pad::Err;
128    type DecryptionKey = Dec::DecryptionKey;
129
130    fn decrypt(
131        &self,
132        mut data: Vec<u8>,
133        key: Self::DecryptionKey,
134    ) -> Result<Vec<u8>, Self::DecryptionErr> {
135        let block_size = size_of::<Dec::DecryptionBlock>();
136        let mut prev = self.iv.clone();
137        // Decrypt the blocks in-place, using the input vector.
138        for chunk in data.chunks_mut(block_size) {
139            let block: Dec::DecryptionBlock = chunk.try_into().unwrap();
140            let mut plaintext = self.cip.decrypt(block.clone(), key.clone());
141            plaintext
142                .as_mut()
143                .iter_mut()
144                .zip(prev.into_iter())
145                .for_each(|(a, b): (&mut u8, _)| *a ^= b);
146            chunk.copy_from_slice(plaintext.as_ref());
147            prev = block;
148        }
149        self.pad.unpad(data, block_size)
150    }
151}