1use buffer::{BufferResult, RefReadBuffer, RefWriteBuffer};
13use symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher, SymmetricCipherError};
14use cryptoutil::symm_enc_or_dec;
15
16#[derive(Copy)]
17pub struct Rc4 {
18 i: u8,
19 j: u8,
20 state: [u8; 256]
21}
22
23impl Clone for Rc4 { fn clone(&self) -> Rc4 { *self } }
24
25impl Rc4 {
26 pub fn new(key: &[u8]) -> Rc4 {
27 assert!(key.len() >= 1 && key.len() <= 256);
28 let mut rc4 = Rc4 { i: 0, j: 0, state: [0; 256] };
29 for (i, x) in rc4.state.iter_mut().enumerate() {
30 *x = i as u8;
31 }
32 let mut j: u8 = 0;
33 for i in 0..256 {
34 j = j.wrapping_add(rc4.state[i]).wrapping_add(key[i % key.len()]);
35 rc4.state.swap(i, j as usize);
36 }
37 rc4
38 }
39 fn next(&mut self) -> u8 {
40 self.i = self.i.wrapping_add(1);
41 self.j = self.j.wrapping_add(self.state[self.i as usize]);
42 self.state.swap(self.i as usize, self.j as usize);
43 let k = self.state[(self.state[self.i as usize].wrapping_add(self.state[self.j as usize])) as usize];
44 k
45 }
46}
47
48impl SynchronousStreamCipher for Rc4 {
49 fn process(&mut self, input: &[u8], output: &mut [u8]) {
50 assert!(input.len() == output.len());
51 for (x, y) in input.iter().zip(output.iter_mut()) {
52 *y = *x ^ self.next();
53 }
54 }
55}
56
57impl Encryptor for Rc4 {
58 fn encrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
59 -> Result<BufferResult, SymmetricCipherError> {
60 symm_enc_or_dec(self, input, output)
61 }
62}
63
64impl Decryptor for Rc4 {
65 fn decrypt(&mut self, input: &mut RefReadBuffer, output: &mut RefWriteBuffer, _: bool)
66 -> Result<BufferResult, SymmetricCipherError> {
67 symm_enc_or_dec(self, input, output)
68 }
69}
70
71#[cfg(test)]
72mod test {
73 use std::iter::repeat;
74
75 use symmetriccipher::SynchronousStreamCipher;
76 use rc4::Rc4;
77
78 struct Test {
79 key: &'static str,
80 input: &'static str,
81 output: Vec<u8>
82 }
83
84 fn tests() -> Vec<Test> {
85 vec![
86 Test {
87 key: "Key",
88 input: "Plaintext",
89 output: vec![0xBB, 0xF3, 0x16, 0xE8, 0xD9, 0x40, 0xAF, 0x0A, 0xD3]
90 },
91 Test {
92 key: "Wiki",
93 input: "pedia",
94 output: vec![0x10, 0x21, 0xBF, 0x04, 0x20]
95 },
96 Test {
97 key: "Secret",
98 input: "Attack at dawn",
99 output: vec![0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B,
100 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5]
101 }
102 ]
103 }
104
105 #[test]
106 fn wikipedia_tests() {
107 let tests = tests();
108 for t in tests.iter() {
109 let mut rc4 = Rc4::new(t.key.as_bytes());
110 let mut result: Vec<u8> = repeat(0).take(t.output.len()).collect();
111 rc4.process(t.input.as_bytes(), &mut result);
112 assert!(result == t.output);
113 }
114 }
115}
116
117#[cfg(all(test, feature = "with-bench"))]
118mod bench {
119 use test::Bencher;
120 use symmetriccipher::SynchronousStreamCipher;
121 use rc4::Rc4;
122
123 #[bench]
124 pub fn rc4_10(bh: & mut Bencher) {
125 let mut rc4 = Rc4::new("key".as_bytes());
126 let input = [1u8; 10];
127 let mut output = [0u8; 10];
128 bh.iter( || {
129 rc4.process(&input, &mut output);
130 });
131 bh.bytes = input.len() as u64;
132 }
133
134 #[bench]
135 pub fn rc4_1k(bh: & mut Bencher) {
136 let mut rc4 = Rc4::new("key".as_bytes());
137 let input = [1u8; 1024];
138 let mut output = [0u8; 1024];
139 bh.iter( || {
140 rc4.process(&input, &mut output);
141 });
142 bh.bytes = input.len() as u64;
143 }
144
145 #[bench]
146 pub fn rc4_64k(bh: & mut Bencher) {
147 let mut rc4 = Rc4::new("key".as_bytes());
148 let input = [1u8; 65536];
149 let mut output = [0u8; 65536];
150 bh.iter( || {
151 rc4.process(&input, &mut output);
152 });
153 bh.bytes = input.len() as u64;
154 }
155}