1use const_for::const_for;
2
3pub struct XorConst {}
4
5impl XorConst {
6 pub const fn encrypt<const N: usize, const K: usize>(
7 plaintext: &[u8; N],
8 key: &[u8; K],
9 ) -> [u8; N] {
10 if K == 0 {
11 panic!("Key cannot be empty");
12 }
13
14 let mut ciphertext = [0u8; N];
15 const_for!(i in 0..N => {
16 ciphertext[i] = plaintext[i] ^ key[i % K];
17 });
18
19 ciphertext
20 }
21
22 pub const fn decrypt<const N: usize, const K: usize>(
23 ciphertext: &[u8; N],
24 key: &[u8; K],
25 ) -> [u8; N] {
26 Self::encrypt(ciphertext, key)
27 }
28}
29
30pub struct Xor {}
31
32impl Xor {
33 pub fn encrypt<const N: usize, const K: usize>(plaintext: &[u8; N], key: &[u8; K]) -> [u8; N] {
34 if K == 0 {
35 panic!("Key cannot be empty");
36 }
37
38 let mut ciphertext = [0u8; N];
39 const_for!(i in 0..N => {
40 ciphertext[i] = plaintext[i] ^ key[i % K];
41 });
42
43 ciphertext
44 }
45
46 pub fn decrypt<const N: usize, const K: usize>(ciphertext: &[u8; N], key: &[u8; K]) -> [u8; N] {
47 Self::encrypt(ciphertext, key)
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use crate::xor::XorConst;
54
55 #[test]
56 fn test_const_mode() {
57 let plaintext = [0u8; 16];
58 let key = [0xFF; 16];
59
60 let ciphertext = XorConst::encrypt(&plaintext, &key);
61 let decrypted = XorConst::decrypt(&ciphertext, &key);
62
63 assert_eq!(
64 decrypted, plaintext,
65 "Decrypted text does not match original plaintext"
66 );
67 }
68
69 use crate::xor::Xor;
70
71 #[test]
72 fn test_nonconst_mode() {
73 let plaintext = [0u8; 16];
74 let key = [0xFF; 16];
75
76 let ciphertext = Xor::encrypt(&plaintext, &key);
77 let decrypted = Xor::decrypt(&ciphertext, &key);
78
79 assert_eq!(
80 decrypted, plaintext,
81 "Decrypted text does not match original plaintext"
82 );
83 }
84}