longest period finder

This commit is contained in:
2026-04-07 11:36:03 +02:00
parent 2c4d3d2af3
commit caaabe204e
2 changed files with 49 additions and 4 deletions

View File

@@ -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);
}

View File

@@ -66,6 +66,19 @@ pub fn period_floyd(key: Vec<u8>, iv: Vec<u8>) -> 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<u8>) -> 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)
}