period finder
This commit is contained in:
+163
@@ -0,0 +1,163 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::tea3::Tea3;
|
||||
|
||||
/// period brute force with hashmap
|
||||
pub fn period_bruteforce(key: Vec<u8>, iv: Vec<u8>) -> u64 {
|
||||
let mut cipher = Tea3::new(key, iv);
|
||||
cipher.init();
|
||||
|
||||
let mut seen = HashMap::new();
|
||||
let mut step: u64 = 0;
|
||||
|
||||
loop {
|
||||
let state = (
|
||||
cipher.key_register().to_vec(),
|
||||
cipher.state_register().to_vec(),
|
||||
);
|
||||
|
||||
if let Some(prev) = seen.get(&state) {
|
||||
return step - prev;
|
||||
}
|
||||
|
||||
seen.insert(state, step);
|
||||
|
||||
cipher.step();
|
||||
step += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// period brute force with Floyd tortoise and hare algorithm
|
||||
pub fn period_floyd(key: Vec<u8>, iv: Vec<u8>) -> u64 {
|
||||
let mut tortoise = Tea3::new(key.clone(), iv.clone());
|
||||
let mut hare = Tea3::new(key, iv);
|
||||
|
||||
tortoise.init();
|
||||
hare.init();
|
||||
|
||||
tortoise.step();
|
||||
hare.step();
|
||||
hare.step();
|
||||
|
||||
while (tortoise.key_register(), tortoise.state_register())
|
||||
!= (hare.key_register(), hare.state_register())
|
||||
{
|
||||
tortoise.step();
|
||||
hare.step();
|
||||
hare.step();
|
||||
}
|
||||
|
||||
let mut lambda = 1;
|
||||
hare.step();
|
||||
|
||||
while (tortoise.key_register(), tortoise.state_register())
|
||||
!= (hare.key_register(), hare.state_register())
|
||||
{
|
||||
hare.step();
|
||||
lambda += 1;
|
||||
}
|
||||
|
||||
lambda
|
||||
}
|
||||
|
||||
// paper method, decomposition key register
|
||||
// (Observations on TETRA Encryption Algorithm TEA-3)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
struct Reg5([u8; 5]);
|
||||
|
||||
impl Reg5 {
|
||||
fn step_h(&mut self) -> u8 {
|
||||
let out = self.0[0];
|
||||
let feedback = out ^ Tea3::p(self.0[2]);
|
||||
|
||||
self.0.copy_within(1..5, 0);
|
||||
self.0[4] = feedback;
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn step_g(&mut self, h_out: u8) -> u8 {
|
||||
let out = self.0[0];
|
||||
let feedback = out ^ h_out;
|
||||
|
||||
self.0.copy_within(1..5, 0);
|
||||
self.0[4] = feedback;
|
||||
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
struct Decomposed {
|
||||
g: Reg5,
|
||||
h: Reg5,
|
||||
}
|
||||
|
||||
impl Decomposed {
|
||||
fn from_key(key: &[u8]) -> Self {
|
||||
Self {
|
||||
g: Reg5([key[0], key[1], key[2], key[3], key[4]]),
|
||||
h: Reg5([
|
||||
key[0] ^ key[5],
|
||||
key[1] ^ key[6],
|
||||
key[2] ^ key[7],
|
||||
key[3] ^ key[8],
|
||||
key[4] ^ key[9],
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
fn step(&mut self) -> u8 {
|
||||
let h_out = self.h.step_h();
|
||||
self.g.step_g(h_out)
|
||||
}
|
||||
}
|
||||
|
||||
fn period_h(start: Reg5) -> u64 {
|
||||
let mut tortoise = start;
|
||||
let mut hare = start;
|
||||
|
||||
tortoise.step_h();
|
||||
hare.step_h();
|
||||
hare.step_h();
|
||||
|
||||
while tortoise != hare {
|
||||
tortoise.step_h();
|
||||
hare.step_h();
|
||||
hare.step_h();
|
||||
}
|
||||
|
||||
let mut lambda = 1;
|
||||
hare.step_h();
|
||||
|
||||
while tortoise != hare {
|
||||
hare.step_h();
|
||||
lambda += 1;
|
||||
}
|
||||
|
||||
lambda
|
||||
}
|
||||
|
||||
/// paper method, decomposition key register
|
||||
/// (Observations on TETRA Encryption Algorithm TEA-3)
|
||||
pub fn period_paper(key: Vec<u8>) -> u64 {
|
||||
let start = Decomposed::from_key(&key);
|
||||
|
||||
let p = period_h(start.h);
|
||||
|
||||
for mult in [1u64, 2, 5, 10] {
|
||||
let target = p * mult;
|
||||
|
||||
let mut cur = start;
|
||||
|
||||
for _ in 0..target {
|
||||
cur.step();
|
||||
}
|
||||
|
||||
if cur == start {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
panic!("No valid period found");
|
||||
}
|
||||
Reference in New Issue
Block a user