use noxtls_core::{Error, Result};
#[derive(Debug, Clone)]
pub struct Rc4 {
s: [u8; 256],
i: u8,
j: u8,
}
impl Rc4 {
pub fn new(key: &[u8]) -> Result<Self> {
if key.is_empty() {
return Err(Error::InvalidLength("rc4 key must not be empty"));
}
let mut s = [0_u8; 256];
for (idx, entry) in s.iter_mut().enumerate() {
*entry = idx as u8;
}
let mut j = 0_u8;
for i in 0..256_u16 {
let idx = i as usize;
j = j.wrapping_add(s[idx]).wrapping_add(key[idx % key.len()]);
s.swap(idx, usize::from(j));
}
Ok(Self { s, i: 0, j: 0 })
}
fn next_byte(&mut self) -> u8 {
self.i = self.i.wrapping_add(1);
self.j = self.j.wrapping_add(self.s[usize::from(self.i)]);
self.s.swap(usize::from(self.i), usize::from(self.j));
let t = self.s[usize::from(self.i)].wrapping_add(self.s[usize::from(self.j)]);
self.s[usize::from(t)]
}
pub fn apply_keystream(&mut self, input: &[u8], output: &mut [u8]) -> Result<()> {
if input.len() != output.len() {
return Err(Error::InvalidLength("input and output length mismatch"));
}
for (in_byte, out_byte) in input.iter().zip(output.iter_mut()) {
*out_byte = *in_byte ^ self.next_byte();
}
Ok(())
}
}