dbids_aes/
aes_ecb.rs

1//! AES Electronic Code Book (ECB) Mode of Operation
2//  Devin Bidstrup 6/27/25
3
4use crate::aes::{aes_128, aes_192, aes_256};
5use std::convert::TryInto;
6
7const BLOCKLEN: usize = 16; // Block length in bytes - AES is 128b block only
8
9/// This function applies AES encryption or decryption to each block in the input data
10/// using the specified key in place. The operation is determined by the `is_encrypt` parameter.
11///
12/// # Arguments
13/// * `key` - The AES key to use for encryption or decryption.  Given as a fixed-size(16B, 24B, 32B) array of bytes.
14/// * `data` - An immutable reference to a slice of bytes to process.  Bytes must be a multiple of 16 bytes or 128 bits, otherwise the function will panic.
15/// * `is_encrypt` - A boolean indicating whether to encrypt (true) or decrypt (false).
16///
17/// # Returns
18/// A vector of processed blocks after applying AES in ECB mode.
19pub fn aes_ecb(key: &[u8], data: &mut [u8], is_encrypt: bool) {
20  assert!(
21    data.len() % BLOCKLEN == 0,
22    "Data length must be a multiple of {} bytes.",
23    BLOCKLEN
24  );
25
26  for block in data.chunks_mut(BLOCKLEN) {
27    let temp_block = match key.len() {
28      16 => aes_128(
29        key.try_into().unwrap(),
30        block.try_into().unwrap(),
31        is_encrypt,
32      ),
33      24 => aes_192(
34        key.try_into().unwrap(),
35        block.try_into().unwrap(),
36        is_encrypt,
37      ),
38      32 => aes_256(
39        key.try_into().unwrap(),
40        block.try_into().unwrap(),
41        is_encrypt,
42      ),
43      _ => panic!("Invalid key length. Must be 128, 192, or 256 bits."),
44    };
45    block.copy_from_slice(&temp_block);
46  }
47}
48
49// ------------------------------------------ Unit Tests ------------------------------------------
50#[cfg(test)]
51mod tests {
52  use super::*;
53  #[test]
54  // Example from: SP800-38A, Appendix F
55  fn test_aes_128_ecb() {
56    let key: [u8; 16] = 0x2b7e151628aed2a6abf7158809cf4f3c_u128.to_be_bytes();
57    let plaintext: [u8; 64] = [
58      0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17,
59      0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF,
60      0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A,
61      0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B,
62      0xE6, 0x6C, 0x37, 0x10,
63    ];
64    let exp_ciphertext: [u8; 64] = [
65      0x3A, 0xD7, 0x7B, 0xB4, 0x0D, 0x7A, 0x36, 0x60, 0xA8, 0x9E, 0xCA, 0xF3, 0x24, 0x66, 0xEF,
66      0x97, 0xF5, 0xD3, 0xD5, 0x85, 0x03, 0xB9, 0x69, 0x9D, 0xE7, 0x85, 0x89, 0x5A, 0x96, 0xFD,
67      0xBA, 0xAF, 0x43, 0xB1, 0xCD, 0x7F, 0x59, 0x8E, 0xCE, 0x23, 0x88, 0x1B, 0x00, 0xE3, 0xED,
68      0x03, 0x06, 0x88, 0x7B, 0x0C, 0x78, 0x5E, 0x27, 0xE8, 0xAD, 0x3F, 0x82, 0x23, 0x20, 0x71,
69      0x04, 0x72, 0x5D, 0xD4,
70    ];
71    test_aes_ecb_comm(&key, plaintext, exp_ciphertext);
72  }
73
74  #[test]
75  // Example from: SP800-38A, Appendix F
76  fn test_aes_192_ecb() {
77    let key: [u8; 24] = [
78      0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79,
79      0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
80    ];
81
82    let plaintext: [u8; 64] = [
83      0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17,
84      0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF,
85      0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A,
86      0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B,
87      0xE6, 0x6C, 0x37, 0x10,
88    ];
89    let exp_ciphertext: [u8; 64] = [
90      0xBD, 0x33, 0x4F, 0x1D, 0x6E, 0x45, 0xF2, 0x5F, 0xF7, 0x12, 0xA2, 0x14, 0x57, 0x1F, 0xA5,
91      0xCC, 0x97, 0x41, 0x04, 0x84, 0x6D, 0x0A, 0xD3, 0xAD, 0x77, 0x34, 0xEC, 0xB3, 0xEC, 0xEE,
92      0x4E, 0xEF, 0xEF, 0x7A, 0xFD, 0x22, 0x70, 0xE2, 0xE6, 0x0A, 0xDC, 0xE0, 0xBA, 0x2F, 0xAC,
93      0xE6, 0x44, 0x4E, 0x9A, 0x4B, 0x41, 0xBA, 0x73, 0x8D, 0x6C, 0x72, 0xFB, 0x16, 0x69, 0x16,
94      0x03, 0xC1, 0x8E, 0x0E,
95    ];
96    test_aes_ecb_comm(&key, plaintext, exp_ciphertext);
97  }
98
99  #[test]
100  // Example from: SP800-38A, Appendix F
101  fn test_aes_256_ecb() {
102    let key: [u8; 32] = [
103      0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77,
104      0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14,
105      0xdf, 0xf4,
106    ];
107    let plaintext: [u8; 64] = [
108      0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17,
109      0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF,
110      0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A,
111      0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B,
112      0xE6, 0x6C, 0x37, 0x10,
113    ];
114    let exp_ciphertext: [u8; 64] = [
115      0xF3, 0xEE, 0xD1, 0xBD, 0xB5, 0xD2, 0xA0, 0x3C, 0x06, 0x4B, 0x5A, 0x7E, 0x3D, 0xB1, 0x81,
116      0xF8, 0x59, 0x1C, 0xCB, 0x10, 0xD4, 0x10, 0xED, 0x26, 0xDC, 0x5B, 0xA7, 0x4A, 0x31, 0x36,
117      0x28, 0x70, 0xB6, 0xED, 0x21, 0xB9, 0x9C, 0xA6, 0xF4, 0xF9, 0xF1, 0x53, 0xE7, 0xB1, 0xBE,
118      0xAF, 0xED, 0x1D, 0x23, 0x30, 0x4B, 0x7A, 0x39, 0xF9, 0xF3, 0xFF, 0x06, 0x7D, 0x8D, 0x8F,
119      0x9E, 0x24, 0xEC, 0xC7,
120    ];
121    test_aes_ecb_comm(&key, plaintext, exp_ciphertext);
122  }
123
124  fn test_aes_ecb_comm(key: &[u8], plaintext: [u8; 64], exp_ciphertext: [u8; 64]) {
125    println!("---------------------Before Encryption:---------------------\n");
126    println!("plaintext: {:x?}", plaintext);
127    println!("key: {:x?}", key);
128
129    let mut act_ciphertext: [u8; 64] = plaintext;
130    aes_ecb(key, &mut act_ciphertext, true);
131
132    println!("---------------------After Encryption:---------------------\n");
133    println!("actual ciphertext: {:x?}", act_ciphertext);
134    println!("expected ciphertext: {:x?}\n", exp_ciphertext);
135    assert_eq!(exp_ciphertext, act_ciphertext);
136
137    let mut act_plaintext = act_ciphertext;
138    aes_ecb(key, &mut act_plaintext, false);
139
140    println!("---------------------After Decryption:---------------------\n");
141    println!("actual plaintext: {:x?}", act_plaintext);
142    println!("expected plaintext: {:x?}", plaintext);
143    assert_eq!(plaintext, act_plaintext);
144  }
145}