custom feedback
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -3,5 +3,5 @@
|
|||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lfsr"
|
name = "tea-3"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lfsr"
|
name = "tea-3"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|||||||
68
src/lfsr.rs
68
src/lfsr.rs
@@ -6,6 +6,14 @@ pub struct Lfsr {
|
|||||||
taps: Vec<usize>,
|
taps: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type FeedbackFn = fn(&[u8]) -> u8;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
pub struct StepConfig {
|
||||||
|
/// Computes feedback from the selected bytes.
|
||||||
|
pub feedback: Option<FeedbackFn>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Lfsr {
|
impl Lfsr {
|
||||||
/// Create a new LFSR
|
/// Create a new LFSR
|
||||||
///
|
///
|
||||||
@@ -44,6 +52,36 @@ impl Lfsr {
|
|||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generic step:
|
||||||
|
pub fn next_custom(&mut self, feedback_indices: &[usize], cfg: StepConfig) -> u8 {
|
||||||
|
let output = *self.state.last().unwrap();
|
||||||
|
|
||||||
|
for &idx in feedback_indices {
|
||||||
|
assert!(idx < self.state.len(), "Feedback index out of bounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
let selected: Vec<u8> = feedback_indices
|
||||||
|
.iter()
|
||||||
|
.map(|&idx| self.state[idx])
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let feedback = if let Some(f) = cfg.feedback {
|
||||||
|
f(&selected)
|
||||||
|
} else {
|
||||||
|
// Default: XOR
|
||||||
|
selected.iter().copied().fold(0u8, |acc, b| acc ^ b)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shift right
|
||||||
|
for i in (1..self.state.len()).rev() {
|
||||||
|
self.state[i] = self.state[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state[0] = feedback;
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
/// Get current state
|
/// Get current state
|
||||||
pub fn state(&self) -> &[u8] {
|
pub fn state(&self) -> &[u8] {
|
||||||
&self.state
|
&self.state
|
||||||
@@ -86,6 +124,36 @@ mod tests {
|
|||||||
assert_eq!(lfsr.state(), &[3, 1, 2]);
|
assert_eq!(lfsr.state(), &[3, 1, 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_next_custom() {
|
||||||
|
// S-box placeholder: S(n) = n + 15
|
||||||
|
// + are XOR in this context
|
||||||
|
fn s(x: u8) -> u8 {
|
||||||
|
x ^ 15
|
||||||
|
}
|
||||||
|
|
||||||
|
// feedback = k0 + S(k2 + k7)
|
||||||
|
let mut lfsr = Lfsr::new(10, vec![], vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||||
|
|
||||||
|
let output = lfsr.next_custom(
|
||||||
|
&[0, 2, 7],
|
||||||
|
StepConfig {
|
||||||
|
feedback: Some(|b| b[0] ^ s(b[1] ^ b[2])),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Expected:
|
||||||
|
// k0 = 1
|
||||||
|
// k2 = 3
|
||||||
|
// k7 = 8
|
||||||
|
// k2 + k7 = 3 + 8 = 11
|
||||||
|
// s(11) = 11 + 15 = 4
|
||||||
|
// feedback = 1 + 4 = 5
|
||||||
|
|
||||||
|
assert_eq!(output, 10);
|
||||||
|
assert_eq!(lfsr.state(), &[5, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_taps() {
|
fn test_empty_taps() {
|
||||||
let mut lfsr = Lfsr::new(3, vec![], vec![1, 2, 3]);
|
let mut lfsr = Lfsr::new(3, vec![], vec![1, 2, 3]);
|
||||||
|
|||||||
Reference in New Issue
Block a user