1use crate::aes::{aes_128, aes_192, aes_256};
5use std::convert::TryInto;
6
7const BLOCKLEN: usize = 16; pub fn aes_cbc(key: &[u8], data: &mut [u8], iv: u128, is_encrypt: bool) {
26 assert!(
27 data.len() % BLOCKLEN == 0,
28 "Data length must be a multiple of {} bytes.",
29 BLOCKLEN
30 );
31
32 let mut iv_copy: [u8; BLOCKLEN] = iv.to_be_bytes();
34 let mut xor_copy: Vec<u8> = Vec::with_capacity(data.len());
35 xor_copy.extend_from_slice(&iv.to_be_bytes());
36 xor_copy.extend_from_slice(data.split_at(data.len() - BLOCKLEN).0);
37
38 for block in data.chunks_mut(BLOCKLEN) {
39 if is_encrypt {
41 block.iter_mut().enumerate().for_each(|(i, byte)| {
42 *byte ^= iv_copy[i];
43 });
44 }
45
46 let temp_block = match key.len() {
48 16 => aes_128(
49 key.try_into().unwrap(),
50 block.try_into().unwrap(),
51 is_encrypt,
52 ),
53 24 => aes_192(
54 key.try_into().unwrap(),
55 block.try_into().unwrap(),
56 is_encrypt,
57 ),
58 32 => aes_256(
59 key.try_into().unwrap(),
60 block.try_into().unwrap(),
61 is_encrypt,
62 ),
63 _ => panic!("Invalid key length. Must be 128, 192, or 256 bits."),
64 };
65 block.copy_from_slice(&temp_block);
66
67 if is_encrypt {
69 iv_copy.copy_from_slice(block);
70 }
71 }
72
73 if !is_encrypt {
75 data.iter_mut().enumerate().for_each(|(i, byte)| {
76 *byte ^= xor_copy[i];
77 });
78 }
79}
80
81#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
88 fn test_aes_128_cbc() {
89 let key: [u8; 16] = 0x2b7e151628aed2a6abf7158809cf4f3c_u128.to_be_bytes();
90 let iv: u128 = 0x00010203_04050607_08090a0b_0c0d0e0f;
91 let plaintext: [u8; 64] = [
92 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17,
93 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF,
94 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A,
95 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B,
96 0xE6, 0x6C, 0x37, 0x10,
97 ];
98 let exp_ciphertext: [u8; 64] = [
99 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19,
100 0x7d, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76,
101 0x78, 0xb2, 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22,
102 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30,
103 0x75, 0x86, 0xe1, 0xa7,
104 ];
105 test_aes_cbc_comm(&key, plaintext, exp_ciphertext, iv);
106 }
107
108 #[test]
109 fn test_aes_192_cbc() {
110 let key: [u8; 24] = [
111 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79,
112 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
113 ];
114 let iv: u128 = 0x00010203_04050607_08090a0b_0c0d0e0f;
115 let plaintext: [u8; 64] = [
116 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17,
117 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF,
118 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A,
119 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B,
120 0xE6, 0x6C, 0x37, 0x10,
121 ];
122 let exp_ciphertext: [u8; 64] = [
123 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71,
124 0xe8, 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69,
125 0x14, 0x5a, 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d,
126 0xf1, 0x02, 0xe0, 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, 0xd9, 0x20, 0xa9, 0xe6,
127 0x4f, 0x56, 0x15, 0xcd,
128 ];
129 test_aes_cbc_comm(&key, plaintext, exp_ciphertext, iv);
130 }
131
132 #[test]
133 fn test_aes_256_cbc() {
134 let key: [u8; 32] = [
135 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77,
136 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14,
137 0xdf, 0xf4,
138 ];
139 let iv: u128 = 0x00010203_04050607_08090a0b_0c0d0e0f;
140 let plaintext: [u8; 64] = [
141 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17,
142 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF,
143 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A,
144 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B,
145 0xE6, 0x6C, 0x37, 0x10,
146 ];
147 let exp_ciphertext: [u8; 64] = [
148 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb,
149 0xd6, 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70,
150 0x2c, 0x7d, 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04,
151 0x23, 0x14, 0x61, 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07,
152 0x8c, 0x6a, 0x9d, 0x1b,
153 ];
154 test_aes_cbc_comm(&key, plaintext, exp_ciphertext, iv);
155 }
156
157 fn test_aes_cbc_comm(key: &[u8], plaintext: [u8; 64], exp_ciphertext: [u8; 64], iv: u128) {
158 println!("---------------------Before Encryption:---------------------\n");
159 println!("plaintext: {:x?}", plaintext);
160 println!("key: {:x?}", key);
161
162 let mut act_ciphertext: [u8; 64] = plaintext;
163 aes_cbc(key, &mut act_ciphertext, iv, true);
164
165 println!("---------------------After Encryption:---------------------\n");
166 println!("actual ciphertext: {:x?}", act_ciphertext);
167 println!("expected ciphertext: {:x?}\n", exp_ciphertext);
168 assert_eq!(exp_ciphertext, act_ciphertext);
169
170 let mut act_plaintext = act_ciphertext;
171 aes_cbc(key, &mut act_plaintext, iv, false);
172
173 println!("---------------------After Decryption:---------------------\n");
174 println!("actual plaintext: {:x?}", act_plaintext);
175 println!("expected plaintext: {:x?}", plaintext);
176 assert_eq!(plaintext, act_plaintext);
177 }
178}