const_ciphers/
xor.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use const_for::const_for;

pub struct XorConst {}

impl XorConst {
    pub const fn encrypt<const N: usize, const K: usize>(
        plaintext: &[u8; N],
        key: &[u8; K],
    ) -> [u8; N] {
        if K == 0 {
            panic!("Key cannot be empty");
        }

        let mut ciphertext = [0u8; N];
        const_for!(i in 0..N => {
            ciphertext[i] = plaintext[i] ^ key[i % K];
        });

        ciphertext
    }

    pub const fn decrypt<const N: usize, const K: usize>(
        ciphertext: &[u8; N],
        key: &[u8; K],
    ) -> [u8; N] {
        Self::encrypt(ciphertext, key)
    }
}

#[cfg(test)]
mod tests {
    use crate::xor::XorConst;

    #[test]
    fn test() {
        let plaintext = [0u8; 16];
        let key = [0xFF; 16];

        let encrypted = XorConst::encrypt(&plaintext, &key);
        let decrypted = XorConst::decrypt(&encrypted, &key);

        assert_eq!(
            decrypted, plaintext,
            "Decrypted text does not match original plaintext"
        );
    }
}