Skip to main content

oxidize_pdf/encryption/
rc4.rs

1//! RC4 encryption algorithm implementation
2
3/// RC4 key for encryption/decryption
4#[derive(Debug, Clone)]
5pub struct Rc4Key {
6    /// Key bytes
7    pub key: Vec<u8>,
8}
9
10impl Rc4Key {
11    /// Create a new RC4 key
12    pub fn new(key: Vec<u8>) -> Self {
13        Self { key }
14    }
15
16    /// Create from slice
17    pub fn from_slice(key: &[u8]) -> Self {
18        Self { key: key.to_vec() }
19    }
20}
21
22/// RC4 cipher state
23pub struct Rc4 {
24    /// State array
25    s: [u8; 256],
26    /// Index i
27    i: usize,
28    /// Index j
29    j: usize,
30}
31
32impl Rc4 {
33    /// Create a new RC4 cipher with the given key
34    pub fn new(key: &Rc4Key) -> Self {
35        let mut s = [0u8; 256];
36
37        // Initialize state array
38        for (i, byte) in s.iter_mut().enumerate() {
39            *byte = i as u8;
40        }
41
42        // Key scheduling algorithm (KSA)
43        let mut j = 0usize;
44        for i in 0..256 {
45            j = (j + s[i] as usize + key.key[i % key.key.len()] as usize) % 256;
46            s.swap(i, j);
47        }
48
49        Self { s, i: 0, j: 0 }
50    }
51
52    /// Process data (encrypt or decrypt - RC4 is symmetric)
53    pub fn process(&mut self, data: &[u8]) -> Vec<u8> {
54        let mut output = Vec::with_capacity(data.len());
55
56        for &byte in data {
57            // Pseudo-random generation algorithm (PRGA)
58            self.i = (self.i + 1) % 256;
59            self.j = (self.j + self.s[self.i] as usize) % 256;
60            self.s.swap(self.i, self.j);
61
62            let k = self.s[(self.s[self.i] as usize + self.s[self.j] as usize) % 256];
63            output.push(byte ^ k);
64        }
65
66        output
67    }
68
69    /// Process data in place
70    pub fn process_in_place(&mut self, data: &mut [u8]) {
71        for byte in data.iter_mut() {
72            // PRGA
73            self.i = (self.i + 1) % 256;
74            self.j = (self.j + self.s[self.i] as usize) % 256;
75            self.s.swap(self.i, self.j);
76
77            let k = self.s[(self.s[self.i] as usize + self.s[self.j] as usize) % 256];
78            *byte ^= k;
79        }
80    }
81}
82
83/// Encrypt data using RC4
84#[allow(dead_code)]
85pub fn rc4_encrypt(key: &Rc4Key, data: &[u8]) -> Vec<u8> {
86    let mut cipher = Rc4::new(key);
87    cipher.process(data)
88}
89
90/// Decrypt data using RC4 (same as encrypt for RC4)
91#[allow(dead_code)]
92pub fn rc4_decrypt(key: &Rc4Key, data: &[u8]) -> Vec<u8> {
93    rc4_encrypt(key, data)
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn test_rc4_key_creation() {
102        let key = Rc4Key::new(vec![1, 2, 3, 4, 5]);
103        assert_eq!(key.key, vec![1, 2, 3, 4, 5]);
104
105        let key2 = Rc4Key::from_slice(&[6, 7, 8]);
106        assert_eq!(key2.key, vec![6, 7, 8]);
107    }
108
109    #[test]
110    fn test_rc4_encryption_decryption() {
111        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
112        let plaintext = b"Hello, World!";
113
114        // Encrypt
115        let ciphertext = rc4_encrypt(&key, plaintext);
116        assert_ne!(ciphertext, plaintext);
117
118        // Decrypt
119        let decrypted = rc4_decrypt(&key, &ciphertext);
120        assert_eq!(decrypted, plaintext);
121    }
122
123    #[test]
124    fn test_rc4_process_in_place() {
125        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
126        let mut data = b"Test data".to_vec();
127        let original = data.clone();
128
129        // Encrypt in place
130        let mut cipher = Rc4::new(&key);
131        cipher.process_in_place(&mut data);
132        assert_ne!(data, original);
133
134        // Decrypt in place
135        let mut cipher = Rc4::new(&key);
136        cipher.process_in_place(&mut data);
137        assert_eq!(data, original);
138    }
139
140    #[test]
141    fn test_rc4_known_vectors() {
142        // Test vector from RFC 6229
143        let key = Rc4Key::from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05]);
144        let mut cipher = Rc4::new(&key);
145
146        // Generate keystream
147        let zeros = vec![0u8; 16];
148        let keystream = cipher.process(&zeros);
149
150        // First 16 bytes of keystream for key [01 02 03 04 05]
151        let expected = [
152            0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27, 0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11,
153            0x18, 0xa8,
154        ];
155
156        assert_eq!(&keystream[..16], &expected[..]);
157    }
158
159    #[test]
160    fn test_rc4_key_debug() {
161        let key = Rc4Key::new(vec![1, 2, 3, 4, 5]);
162        let debug_str = format!("{key:?}");
163        assert!(debug_str.contains("Rc4Key"));
164    }
165
166    #[test]
167    fn test_rc4_key_clone() {
168        let key = Rc4Key::new(vec![1, 2, 3, 4, 5]);
169        let cloned_key = key.clone();
170        assert_eq!(key.key, cloned_key.key);
171    }
172
173    #[test]
174    fn test_rc4_empty_data() {
175        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
176        let empty_data = vec![];
177
178        let result = rc4_encrypt(&key, &empty_data);
179        assert!(result.is_empty());
180
181        let result = rc4_decrypt(&key, &empty_data);
182        assert!(result.is_empty());
183    }
184
185    #[test]
186    fn test_rc4_single_byte() {
187        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
188        let single_byte = vec![0xFF];
189
190        let encrypted = rc4_encrypt(&key, &single_byte);
191        assert_eq!(encrypted.len(), 1);
192
193        let decrypted = rc4_decrypt(&key, &encrypted);
194        assert_eq!(decrypted, single_byte);
195    }
196
197    #[test]
198    fn test_rc4_large_data() {
199        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
200        let large_data = vec![0x42; 1000];
201
202        let encrypted = rc4_encrypt(&key, &large_data);
203        assert_eq!(encrypted.len(), 1000);
204        assert_ne!(encrypted, large_data); // Should be different
205
206        let decrypted = rc4_decrypt(&key, &encrypted);
207        assert_eq!(decrypted, large_data);
208    }
209
210    #[test]
211    fn test_rc4_different_keys_different_output() {
212        let data = b"Hello, World!";
213
214        let key1 = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
215        let key2 = Rc4Key::new(vec![0x05, 0x04, 0x03, 0x02, 0x01]);
216
217        let encrypted1 = rc4_encrypt(&key1, data);
218        let encrypted2 = rc4_encrypt(&key2, data);
219
220        assert_ne!(encrypted1, encrypted2);
221    }
222
223    #[test]
224    fn test_rc4_various_key_lengths() {
225        let data = b"Test data";
226
227        // Test different key lengths
228        let key_8bit = Rc4Key::new(vec![0x01]);
229        let key_40bit = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
230        let key_128bit = Rc4Key::new(vec![
231            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
232            0x0F, 0x10,
233        ]);
234
235        let enc1 = rc4_encrypt(&key_8bit, data);
236        let enc2 = rc4_encrypt(&key_40bit, data);
237        let enc3 = rc4_encrypt(&key_128bit, data);
238
239        // All should produce different outputs
240        assert_ne!(enc1, enc2);
241        assert_ne!(enc2, enc3);
242        assert_ne!(enc1, enc3);
243
244        // But all should decrypt correctly
245        assert_eq!(rc4_decrypt(&key_8bit, &enc1), data);
246        assert_eq!(rc4_decrypt(&key_40bit, &enc2), data);
247        assert_eq!(rc4_decrypt(&key_128bit, &enc3), data);
248    }
249
250    #[test]
251    fn test_rc4_process_in_place_empty() {
252        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
253        let mut data = vec![];
254
255        let mut cipher = Rc4::new(&key);
256        cipher.process_in_place(&mut data);
257
258        assert!(data.is_empty());
259    }
260
261    #[test]
262    fn test_rc4_process_consistency() {
263        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
264        let data = b"Consistency test data";
265
266        // Test that process() and process_in_place() give same results
267        let result1 = {
268            let mut cipher = Rc4::new(&key);
269            cipher.process(data)
270        };
271
272        let result2 = {
273            let mut cipher = Rc4::new(&key);
274            let mut data_copy = data.to_vec();
275            cipher.process_in_place(&mut data_copy);
276            data_copy
277        };
278
279        assert_eq!(result1, result2);
280    }
281
282    #[test]
283    fn test_rc4_stateful_processing() {
284        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
285        let data1 = b"First chunk";
286        let data2 = b"Second chunk";
287
288        // Process in chunks using same cipher instance
289        let mut cipher = Rc4::new(&key);
290        let enc1 = cipher.process(data1);
291        let enc2 = cipher.process(data2);
292
293        // Process all at once using new cipher instance
294        let mut cipher2 = Rc4::new(&key);
295        let mut combined_data = Vec::new();
296        combined_data.extend_from_slice(data1);
297        combined_data.extend_from_slice(data2);
298        let enc_combined = cipher2.process(&combined_data);
299
300        // Results should be the same
301        let chunked_result = [enc1, enc2].concat();
302        assert_eq!(chunked_result, enc_combined);
303    }
304
305    #[test]
306    fn test_rc4_binary_data() {
307        let key = Rc4Key::new(vec![0x01, 0x02, 0x03, 0x04, 0x05]);
308        let binary_data = vec![0x00, 0xFF, 0x80, 0x7F, 0x01, 0xFE, 0x55, 0xAA];
309
310        let encrypted = rc4_encrypt(&key, &binary_data);
311        let decrypted = rc4_decrypt(&key, &encrypted);
312
313        assert_eq!(decrypted, binary_data);
314    }
315}