literate_crypto/cipher/block/modes/
cbc.rs1use {
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#[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 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 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}