const_ciphers/
xor.rs

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}