diff --git a/src/main.rs b/src/main.rs index 9d96b18..dec652e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ mod period; mod tea3; use lfsr::Lfsr; -use period::{period_bruteforce, period_floyd, period_paper}; +use period::{longest_period, period_bruteforce, period_floyd, period_paper}; use tea3::Tea3; fn main() { @@ -50,9 +50,22 @@ fn main() { println!("Decrypted : {:?}", decrypted); println!( - "\nPaper period: {}", - // period_paper(vec![0xc2, 0xc2, 0xc2, 0xc2, 0xc2]) - // period_paper(vec![0xa3, 0xe1, 0x6f, 0x58, 0x05]) + "\nPaper period p0: {}", + period_paper(vec![0xc2, 0xc2, 0xc2, 0xc2, 0xc2]) + ); + println!( + "Paper period p1: {}", + period_paper(vec![0xa3, 0xe1, 0x6f, 0x58, 0x05]) + ); + println!( + "Paper period p14: {}", period_paper(vec![0xe3, 0x61, 0x62, 0x00, 0x00]) ); + + // println!("\nPaper period p20: {}", period_paper(vec![0x7a, 0x02, 0x00, 0x00, 0x00])); + // println!("\nPaper period p27: {}", period_paper(vec![0x00, 0x00, 0x00, 0x00, 0x00])); + + let (p, seed) = longest_period(); + println!("\nLongest period: {}", p); + println!("Seed: {:02x?}", seed); } diff --git a/src/period.rs b/src/period.rs index bc4defb..b6c18c8 100644 --- a/src/period.rs +++ b/src/period.rs @@ -66,6 +66,19 @@ pub fn period_floyd(key: Vec, iv: Vec) -> u64 { struct Reg5([u8; 5]); impl Reg5 { + fn from_u40(x: u64) -> Self { + assert!(x < (1u64 << 40), "value must fit in 40 bits"); + + // Internal order: byte 0 is the first register byte. + Self([ + ((x >> 32) & 0xFF) as u8, + ((x >> 24) & 0xFF) as u8, + ((x >> 16) & 0xFF) as u8, + ((x >> 8) & 0xFF) as u8, + (x & 0xFF) as u8, + ]) + } + fn step_h(&mut self) -> u8 { let out = self.0[0]; let feedback = out ^ Tea3::p(self.0[2]); @@ -145,3 +158,22 @@ pub fn period_paper(key: Vec) -> u64 { let start = Decomposed::from_key(&[0, 0, 0, 0, 0, key[0], key[1], key[2], key[3], key[4]]); period_h(start.h) // p } + +/// Exhaustively scan all 2^40 initial values of h and returns: +/// (longest period found, 5-bytes initial value) +pub fn longest_period() -> (u64, [u8; 5]) { + let mut best_period = 0u64; + let mut best_seed = [0u8; 5]; + + for x in 0u64..(1u64 << 40) { + let seed = Reg5::from_u40(x); + let p = period_h(seed); + + if p > best_period { + best_period = p; + best_seed = seed.0; + } + } + + (best_period, best_seed) +}