crypto/
rc4.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7/*!
8 * An implementation of the RC4 (also sometimes called ARC4) stream cipher. THIS IMPLEMENTATION IS
9 * NOT A FIXED TIME IMPLEMENTATION.
10 */
11
12use 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}