period finder
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
mod lfsr;
|
mod lfsr;
|
||||||
|
mod period;
|
||||||
mod tea3;
|
mod tea3;
|
||||||
|
|
||||||
use lfsr::Lfsr;
|
use lfsr::Lfsr;
|
||||||
use tea3::{Tea3, period_floyd};
|
use period::{period_bruteforce, period_floyd, period_paper};
|
||||||
|
use tea3::Tea3;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut lfsr = Lfsr::new(4, vec![0, 3], vec![0x12, 0x34, 0x56, 0x78]);
|
let mut lfsr = Lfsr::new(4, vec![0, 3], vec![0x12, 0x34, 0x56, 0x78]);
|
||||||
@@ -47,5 +49,8 @@ fn main() {
|
|||||||
|
|
||||||
println!("Decrypted : {:?}", decrypted);
|
println!("Decrypted : {:?}", decrypted);
|
||||||
|
|
||||||
// println!("\nperiod: {}", period_floyd(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0], vec![0; 8]));
|
println!(
|
||||||
|
"\nPaper period: {}",
|
||||||
|
period_paper(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
163
src/period.rs
Normal file
163
src/period.rs
Normal file
@@ -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");
|
||||||
|
}
|
||||||
62
src/tea3.rs
62
src/tea3.rs
@@ -1,5 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Tea3 {
|
pub struct Tea3 {
|
||||||
/// Cipher key register k0..k9
|
/// Cipher key register k0..k9
|
||||||
@@ -207,65 +205,6 @@ fn bp(x: u8) -> u8 {
|
|||||||
| bit(5)
|
| bit(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn period(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
// Move tortoise by 1, hare by 2
|
|
||||||
tortoise.step();
|
|
||||||
hare.step();
|
|
||||||
hare.step();
|
|
||||||
|
|
||||||
while tortoise.key_register() != hare.key_register()
|
|
||||||
|| tortoise.state_register() != hare.state_register()
|
|
||||||
{
|
|
||||||
tortoise.step();
|
|
||||||
|
|
||||||
hare.step();
|
|
||||||
hare.step();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut lambda = 1;
|
|
||||||
hare.step();
|
|
||||||
|
|
||||||
while tortoise.key_register() != hare.key_register()
|
|
||||||
|| tortoise.state_register() != hare.state_register()
|
|
||||||
{
|
|
||||||
hare.step();
|
|
||||||
lambda += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lambda
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -470,7 +409,6 @@ mod tests {
|
|||||||
|
|
||||||
let poly = Lfsr::berlekamp_massey(&keystream);
|
let poly = Lfsr::berlekamp_massey(&keystream);
|
||||||
|
|
||||||
|
|
||||||
let history = &keystream[keystream.len() - (poly.len() - 1)..];
|
let history = &keystream[keystream.len() - (poly.len() - 1)..];
|
||||||
let predicted = Lfsr::predict_next_from_poly(history, &poly);
|
let predicted = Lfsr::predict_next_from_poly(history, &poly);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user