1#![forbid(unsafe_code)]
2
3pub struct RC5 {
4 rounds: u32,
5 sub_keys: Vec<u32>,
6}
7
8impl RC5 {
9 pub fn new(key: &[u8], rounds: u32) -> Self {
10 assert!(rounds > 0, "Number of rounds must be positive");
11 assert!(!key.is_empty(), "Key must not be empty");
12
13 let s = Self::expand_key(key, rounds);
14
15 RC5 {
16 rounds,
17 sub_keys: s,
18 }
19 }
20
21 fn expand_key(key: &[u8], rounds: u32) -> Vec<u32> {
22 const P32: u32 = 0xB7E15163;
23 const Q32: u32 = 0x9E3779B9;
24 let t = 2 * (rounds + 1);
25 let mut s = vec![0u32; t as usize];
26
27 s[0] = P32;
29 for i in 1..t as usize {
30 s[i] = s[i-1].wrapping_add(Q32);
31 }
32
33 let mut l = vec![0u32; (key.len() + 3) / 4];
35 for i in 0..key.len() {
36 l[i / 4] |= (key[i] as u32) << ((i % 4) * 8);
37 }
38
39 let mut i = 0;
40 let mut j = 0;
41 let mut a = 0u32;
42 let mut b = 0u32;
43 let v = 3 * std::cmp::max(t as usize, l.len());
44
45 for _ in 0..v {
46 let rotated = (s[i].wrapping_add(a).wrapping_add(b)).rotate_left(3);
47 s[i] = rotated;
48 a = rotated;
49
50 let rotated_l = (l[j].wrapping_add(a).wrapping_add(b)).rotate_left((a.wrapping_add(b)) as u32);
51 l[j] = rotated_l;
52 b = rotated_l;
53 i = (i + 1) % t as usize;
54 j = (j + 1) % l.len();
55 }
56
57 s
58 }
59
60 pub fn encrypt_block(&self, block: &mut [u8; 8]) {
61 let mut a = u32::from_le_bytes([block[0], block[1], block[2], block[3]]);
62 let mut b = u32::from_le_bytes([block[4], block[5], block[6], block[7]]);
63
64 a = a.wrapping_add(self.sub_keys[0]);
65 b = b.wrapping_add(self.sub_keys[1]);
66
67 for i in 1..=self.rounds {
68 a = (a ^ b).rotate_left(b as u32).wrapping_add(self.sub_keys[2*i as usize]);
69 b = (b ^ a).rotate_left(a as u32).wrapping_add(self.sub_keys[2*i as usize + 1]);
70 }
71
72 block[0..4].copy_from_slice(&a.to_le_bytes());
73 block[4..8].copy_from_slice(&b.to_le_bytes());
74 }
75
76 pub fn decrypt_block(&self, block: &mut [u8; 8]) {
77 let mut a = u32::from_le_bytes([block[0], block[1], block[2], block[3]]);
78 let mut b = u32::from_le_bytes([block[4], block[5], block[6], block[7]]);
79
80 for i in (1..=self.rounds).rev() {
81 b = b.wrapping_sub(self.sub_keys[2*i as usize + 1]).rotate_right(a as u32) ^ a;
82 a = a.wrapping_sub(self.sub_keys[2*i as usize]).rotate_right(b as u32) ^ b;
83 }
84
85 b = b.wrapping_sub(self.sub_keys[1]);
86 a = a.wrapping_sub(self.sub_keys[0]);
87
88 block[0..4].copy_from_slice(&a.to_le_bytes());
89 block[4..8].copy_from_slice(&b.to_le_bytes());
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_encryption_decryption() {
99 let key = b"my secret key";
100 let rounds = 12;
101 let rc5 = RC5::new(key, rounds);
102
103 let mut block = [0u8; 8];
104 block.copy_from_slice(b"testtest");
105
106 let original = block;
107 rc5.encrypt_block(&mut block);
108 assert_ne!(block, original); rc5.decrypt_block(&mut block);
111 assert_eq!(block, original); }
113
114 #[test]
115 #[should_panic(expected = "Number of rounds must be positive")]
116 fn test_invalid_rounds() {
117 let key = b"test key";
118 RC5::new(key, 0);
119 }
120
121 #[test]
122 #[should_panic(expected = "Key must not be empty")]
123 fn test_empty_key() {
124 let key = b"";
125 RC5::new(key, 12);
126 }
127}