pub struct Snow2 {
s: [u32; 16], r1: u32, r2: u32, keystream: [u32; 16], cur_index: usize,
encrypting: bool,
}
impl Snow2 {
pub fn new(key: &[u8], iv: &[u8], encrypting: bool) -> Self {
assert!(key.len() == 16 || key.len() == 32, "Key must be 16 or 32 bytes");
assert!(iv.is_empty() || iv.len() == 4, "IV must be 0 or 4 bytes");
let mut cipher = Snow2 {
s: [0u32; 16],
r1: 0,
r2: 0,
keystream: [0u32; 16],
cur_index: 16, encrypting,
};
cipher.load_key(key);
if iv.len() == 4 {
cipher.s[15] ^= iv[0] as u32;
cipher.s[12] ^= iv[1] as u32;
cipher.s[10] ^= iv[2] as u32;
cipher.s[9] ^= iv[3] as u32;
}
for _ in 0..32 {
cipher.clock_with_feedback();
}
cipher.refresh_keystream();
cipher.cur_index = 0;
cipher
}
fn load_key(&mut self, key: &[u8]) {
if key.len() == 16 {
let k0 = Self::signed_key_word(key, 0);
let k1 = Self::signed_key_word(key, 4);
let k2 = Self::signed_key_word(key, 8);
let k3 = Self::signed_key_word(key, 12);
self.s[15] = k0;
self.s[14] = k1;
self.s[13] = k2;
self.s[12] = k3;
self.s[11] = !k0;
self.s[10] = !k1;
self.s[9] = !k2;
self.s[8] = !k3;
self.s[7] = k0;
self.s[6] = k1;
self.s[5] = k2;
self.s[4] = k3;
self.s[3] = !k0;
self.s[2] = !k1;
self.s[1] = !k2;
self.s[0] = !k3;
} else {
for i in 0..8 {
self.s[15 - i] = Self::signed_key_word(key, i * 4);
}
self.s[7] = !self.s[15];
self.s[6] = !self.s[14];
self.s[5] = !self.s[13];
self.s[4] = !self.s[12];
self.s[3] = !self.s[11];
self.s[2] = !self.s[10];
self.s[1] = !self.s[9];
self.s[0] = !self.s[8];
}
self.r1 = 0;
self.r2 = 0;
}
#[inline]
fn signed_key_word(key: &[u8], offset: usize) -> u32 {
let b0 = key[offset] as i8 as i32;
let b1 = key[offset + 1] as i8 as i32;
let b2 = key[offset + 2] as i8 as i32;
let b3 = key[offset + 3] as i8 as i32;
((b0 << 24) | (b1 << 16) | (b2 << 8) | b3) as u32
}
fn clock_with_feedback(&mut self) {
let new_s = Self::alpha_mul(self.s[0])
^ self.s[2]
^ Self::alpha_inv_mul(self.s[11]);
let outfrom_fsm = self.r1.wrapping_add(self.s[15]) ^ self.r2;
let fsmtmp = self.r2.wrapping_add(self.s[5]);
self.r2 = Self::t_transform(self.r1);
self.r1 = fsmtmp;
for i in 0..15 {
self.s[i] = self.s[i + 1];
}
self.s[15] = new_s ^ outfrom_fsm;
}
fn refresh_keystream(&mut self) {
for i in 0..16 {
let new_s = Self::alpha_mul(self.s[0])
^ self.s[2]
^ Self::alpha_inv_mul(self.s[11]);
let fsmtmp = self.r2.wrapping_add(self.s[5]);
self.r2 = Self::t_transform(self.r1);
self.r1 = fsmtmp;
self.keystream[i] = self.r1.wrapping_add(new_s) ^ self.r2 ^ self.s[1];
for j in 0..15 {
self.s[j] = self.s[j + 1];
}
self.s[15] = new_s;
}
}
#[inline]
fn next_keystream_word(&mut self) -> u32 {
if self.cur_index >= 16 {
self.refresh_keystream();
self.cur_index = 0;
}
let word = self.keystream[self.cur_index];
self.cur_index += 1;
word
}
pub fn process(&mut self, data: &mut [u8]) {
let mut pos = 0;
while pos + 4 <= data.len() {
let ks = self.next_keystream_word();
let word = u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]);
let result = if self.encrypting {
word.wrapping_add(ks)
} else {
word.wrapping_sub(ks)
};
data[pos..pos + 4].copy_from_slice(&result.to_le_bytes());
pos += 4;
}
if pos < data.len() {
let ks_bytes = self.next_keystream_word().to_le_bytes();
for (i, byte) in data[pos..].iter_mut().enumerate() {
if self.encrypting {
*byte = byte.wrapping_add(ks_bytes[i]);
} else {
*byte = byte.wrapping_sub(ks_bytes[i]);
}
}
}
}
#[inline]
fn alpha_mul(w: u32) -> u32 {
(w << 8) ^ SNOW_ALPHA_MUL[(w >> 24) as usize]
}
#[inline]
fn alpha_inv_mul(w: u32) -> u32 {
(w >> 8) ^ SNOW_ALPHAINV_MUL[(w & 0xFF) as usize]
}
#[inline]
fn t_transform(w: u32) -> u32 {
SNOW_T0[(w & 0xFF) as usize]
^ SNOW_T1[((w >> 8) & 0xFF) as usize]
^ SNOW_T2[((w >> 16) & 0xFF) as usize]
^ SNOW_T3[((w >> 24) & 0xFF) as usize]
}
}
include!("snow2_tables.rs");
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encrypt_decrypt_roundtrip() {
let key = [0x42u8; 16];
let iv = [0x01, 0x02, 0x03, 0x04];
let original = b"Hello, Snow2 cipher test data!!!".to_vec(); let mut data = original.clone();
let mut enc = Snow2::new(&key, &iv, true);
enc.process(&mut data);
assert_ne!(data, original);
let mut dec = Snow2::new(&key, &iv, false);
dec.process(&mut data);
assert_eq!(data, original);
}
#[test]
fn test_roundtrip_32byte_key() {
let key = [0x42u8; 32];
let iv = [0x01, 0x02, 0x03, 0x04];
let original = b"Hello, Snow2 cipher test data!!!".to_vec();
let mut data = original.clone();
Snow2::new(&key, &iv, true).process(&mut data);
assert_ne!(data, original);
Snow2::new(&key, &iv, false).process(&mut data);
assert_eq!(data, original);
}
#[test]
fn test_roundtrip_no_iv() {
let key = [0x42u8; 16];
let original = b"Test data without IV provided!!!".to_vec();
let mut data = original.clone();
Snow2::new(&key, &[], true).process(&mut data);
assert_ne!(data, original);
Snow2::new(&key, &[], false).process(&mut data);
assert_eq!(data, original);
}
#[test]
fn test_process_partial_buffer() {
let key = [0x55u8; 16];
let iv = [0x01, 0x02, 0x03, 0x04];
for len in [1, 2, 3, 5, 6, 7] {
let original: Vec<u8> = (0..len).map(|i| i as u8).collect();
let mut data = original.clone();
Snow2::new(&key, &iv, true).process(&mut data);
Snow2::new(&key, &iv, false).process(&mut data);
assert_eq!(data, original, "Failed for len={}", len);
}
}
#[test]
fn test_process_empty_data() {
let key = [0x42u8; 16];
let iv = [0x01, 0x02, 0x03, 0x04];
let mut data: Vec<u8> = vec![];
Snow2::new(&key, &iv, true).process(&mut data);
assert!(data.is_empty());
}
#[test]
fn test_determinism() {
let key = [0x42u8; 16];
let iv = [0x01, 0x02, 0x03, 0x04];
let original = b"Determinism verification test!!!!".to_vec();
let mut data1 = original.clone();
let mut data2 = original.clone();
Snow2::new(&key, &iv, true).process(&mut data1);
Snow2::new(&key, &iv, true).process(&mut data2);
assert_eq!(data1, data2);
}
}