Newer
Older
for d in data.iter_mut() {
let b;
(b, state) = lfsr_byte(state);
*d ^= b;
}
}
// (byte, state)
fn lfsr_byte(mut state: u16) -> (u8, u16) {
let mut out = 0;
for i in (0..8).rev() {
out |= u8::try_from(state & 1).unwrap() << i;
state = lfsr(state);
}
(out, state)
}
// https://en.wikipedia.org/wiki/Linear-feedback_shift_register#Galois_LFSRs
fn lfsr(mut state: u16) -> u16 {
let lsb = state & 1;
state >>= 1;
if lsb > 0 {
state ^= 0xB400; // apply toggle mask
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
let mut data = [0; 64];
data[0..57]
.clone_from_slice(&b"Hello world! The quick brown fox jumped over the lazy dog"[..]);
whiten(&mut data);
assert_ne!(orig, data);
whiten(&mut data);
assert_eq!(orig, data);
}
#[test]
fn test_lfsr() {
let start = 0xACE1;
let end_expected = 0xE270;
let state = lfsr(start);
assert_eq!(end_expected, state);
}
#[test]
fn test_lfsr_byte() {
let start = 0xE9CF;
let (out, state) = lfsr_byte(start);
assert_eq!(0xF3, out);
assert_eq!(0xE3B1, state);
}
#[test]
fn test_doc_example() {
let start = 0xE9CF;
let expected_out = [
0xF3, 0x8D, 0xD0, 0x6E, 0x1F, 0x65, 0x75, 0x75, 0xA5, 0xBA, 0xA9, 0xD0, 0x7A, 0x1D,
0x1, 0x21,
];
let mut actual_out = [0; 16];
let mut state = start;
}
assert_eq!(expected_out, actual_out);
}
#[test]
fn test_doc_example_through_whitener() {
let expected_out = [
0xF3, 0x8D, 0xD0, 0x6E, 0x1F, 0x65, 0x75, 0x75, 0xA5, 0xBA, 0xA9, 0xD0, 0x7A, 0x1D,
0x1, 0x21,
];
let mut actual_out = [0; 16];
whiten(&mut actual_out);
assert_eq!(expected_out, actual_out);
}