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