6 changed files with 838 additions and 173 deletions
@ -0,0 +1,16 @@ |
|||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion}; |
||||
|
use idea::{decrypt, encrypt}; |
||||
|
|
||||
|
pub fn criterion_benchmark(c: &mut Criterion) { |
||||
|
c.bench_function("encrypt ", |b| { |
||||
|
b.iter(|| { |
||||
|
encrypt( |
||||
|
black_box(0x9d31ccc9ce639084e2f1f70541285b8d), |
||||
|
black_box(0xba431a8cfda88c8f), |
||||
|
) |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
criterion_group!(benches, criterion_benchmark); |
||||
|
criterion_main!(benches); |
@ -0,0 +1,218 @@ |
|||||
|
use modinverse::modinverse; |
||||
|
|
||||
|
struct Vr { |
||||
|
v1: u16, |
||||
|
v2: u16, |
||||
|
v3: u16, |
||||
|
v4: u16, |
||||
|
} |
||||
|
|
||||
|
impl Vr { |
||||
|
fn split(v: u64) -> Self { |
||||
|
let v4 = (v & 0xFFFF) as u16; |
||||
|
let v3 = ((v >> 16) & 0xFFFF) as u16; |
||||
|
let v2 = ((v >> 32) & 0xFFFF) as u16; |
||||
|
let v1 = ((v >> 48) & 0xFFFF) as u16; |
||||
|
Self { |
||||
|
v1: v1, |
||||
|
v2: v2, |
||||
|
v3: v3, |
||||
|
v4: v4, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fn expand(&self) -> u64 { |
||||
|
(self.v1 as u64 * 2_u64.pow(48)) |
||||
|
+ (self.v2 as u64 * 2_u64.pow(32)) |
||||
|
+ (self.v3 as u64 * 2_u64.pow(16)) |
||||
|
+ self.v4 as u64 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
struct Keys { |
||||
|
z1: u16, |
||||
|
z2: u16, |
||||
|
z3: u16, |
||||
|
z4: u16, |
||||
|
z5: u16, |
||||
|
z6: u16, |
||||
|
} |
||||
|
|
||||
|
fn derive_keys(mut k: u128) -> Vec<Keys> { |
||||
|
let mut keys: Vec<Keys> = Vec::new(); |
||||
|
|
||||
|
let mut subkeys = Vec::new(); |
||||
|
while subkeys.len() < 52 { |
||||
|
subkeys.push((k & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 16) & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 32) & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 48) & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 64) & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 80) & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 96) & 0xFFFF) as u16); |
||||
|
subkeys.push(((k >> 112) & 0xFFFF) as u16); |
||||
|
k = k.rotate_left(25); |
||||
|
} |
||||
|
let mut i = 0; |
||||
|
while keys.len() < 8 { |
||||
|
keys.push(Keys { |
||||
|
z1: subkeys[0 + i], |
||||
|
z2: subkeys[1 + i], |
||||
|
z3: subkeys[2 + i], |
||||
|
z4: subkeys[3 + i], |
||||
|
z5: subkeys[4 + i], |
||||
|
z6: subkeys[5 + i], |
||||
|
}); |
||||
|
i = i + 1; |
||||
|
} |
||||
|
keys.push(Keys { |
||||
|
z1: subkeys[0 + i], |
||||
|
z2: subkeys[1 + i], |
||||
|
z3: subkeys[2 + i], |
||||
|
z4: subkeys[3 + i], |
||||
|
z5: 0, |
||||
|
z6: 0, |
||||
|
}); |
||||
|
keys |
||||
|
} |
||||
|
|
||||
|
fn add(a: u16, b: u16) -> u16 { |
||||
|
let (a, b, m) = (a as i32, b as i32, 0x10000 as i32); |
||||
|
((a + b) % m) as u16 |
||||
|
} |
||||
|
|
||||
|
// 0010 0110 % 10001 -> 0010 * (-0001) + 0110 -> 0110
|
||||
|
fn slow_mul(a: u16, b: u16) -> u16 { |
||||
|
let (a, b, m) = (a as u32, b as u32, 0x10001 as u32); |
||||
|
let a = if a == 0 {0x10000} else {a}; |
||||
|
let b = if b == 0 {0x10000} else {b}; |
||||
|
((a * b) % m) as u16 |
||||
|
} |
||||
|
|
||||
|
fn mul(a: u16, b: u16) -> u16 { |
||||
|
let (a, b) = (a as u32, b as u32); |
||||
|
if a == 0 && b == 0 { return 1 } |
||||
|
let a = if a == 0 { 0x10000 } else { a }; |
||||
|
let b = if b == 0 { 0x10000 } else { b }; |
||||
|
let ab = a * b; |
||||
|
let ab_high = ab >> 16; |
||||
|
let ab_low = ab & 0xffff; |
||||
|
let m = if ab_high > ab_low { 0x10001 } else { 0 }; |
||||
|
(ab_low + m - ab_high) as u16 |
||||
|
} |
||||
|
|
||||
|
fn idea_round(ks: &Keys, xs: Vr) -> Vr { |
||||
|
let u1 = mul(ks.z1, xs.v1); |
||||
|
let u2 = mul(ks.z2, xs.v2); |
||||
|
let u3 = add(ks.z3, xs.v3); |
||||
|
let u4 = add(ks.z4, xs.v4); |
||||
|
let u13 = u1 ^ u3; |
||||
|
let u24 = u2 ^ u4; |
||||
|
let u5 = mul(ks.z5, u13); |
||||
|
let c1 = mul(ks.z6, add(u24, u5)); |
||||
|
let c2 = add(u5, c1); |
||||
|
Vr { |
||||
|
v1: c1 ^ u3, |
||||
|
v2: c2 ^ u4, |
||||
|
v3: c1 ^ u1, |
||||
|
v4: c2 ^ u2, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fn idea_finish(ks: &Keys, xs: Vr) -> Vr { |
||||
|
let u1 = mul(ks.z1, xs.v1); |
||||
|
let u2 = mul(ks.z2, xs.v2); |
||||
|
let u3 = add(ks.z3, xs.v3); |
||||
|
let u4 = add(ks.z4, xs.v4); |
||||
|
Vr { |
||||
|
v1: u1, |
||||
|
v2: u2, |
||||
|
v3: u3, |
||||
|
v4: u4, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fn invert_keys(ks: &Keys, z5: u16, z6: u16) -> Keys { |
||||
|
let mut z1 = ks.z1 as i32; |
||||
|
let mut z2 = ks.z2 as i32; |
||||
|
if ks.z1 == 0 { |
||||
|
z1 = 0x010000 as i32; |
||||
|
} |
||||
|
if ks.z2 == 0 { |
||||
|
z2 = 0x010000 as i32; |
||||
|
} |
||||
|
Keys { |
||||
|
z1: modinverse(z1 as i32, 0x0010001 as i32).expect("Modular inverse of z1 doesn't exist!") |
||||
|
as u16, |
||||
|
z2: modinverse(z2 as i32, 0x0010001 as i32).expect("Modular inverse of z2 doesn't exist!") |
||||
|
as u16, |
||||
|
z3: (0x10000 as u32 - ks.z3 as u32) as u16, |
||||
|
z4: (0x10000 as u32 - ks.z4 as u32) as u16, |
||||
|
z5: z5, |
||||
|
z6: z6, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pub fn encrypt(k: u128, m: u64) -> u64 { |
||||
|
let xr = Vr::split(m); |
||||
|
assert_eq!(m, xr.expand()); |
||||
|
// Derive keys
|
||||
|
let kr = derive_keys(k); |
||||
|
|
||||
|
let mut bs = xr; |
||||
|
let mut i = 0; |
||||
|
while i < 8 { |
||||
|
// println!("Round {i}:");
|
||||
|
bs = idea_round(&kr[i], bs); |
||||
|
// println!("intermediate result: {:?}\n", bs.expand());
|
||||
|
i = i + 1; |
||||
|
} |
||||
|
let ys = idea_finish(&kr[8], bs); |
||||
|
ys.expand() |
||||
|
} |
||||
|
|
||||
|
pub fn decrypt(k: u128, m: u64) -> u64 { |
||||
|
let xr = Vr::split(m); |
||||
|
assert_eq!(m, xr.expand()); |
||||
|
// Derive and invert keys
|
||||
|
let kr = derive_keys(k); |
||||
|
let mut dr: Vec<Keys> = Vec::new(); |
||||
|
let mut i = 8; |
||||
|
while i > 0 { |
||||
|
let ds = invert_keys(&kr[i], kr[i - 1].z5, kr[i - 1].z6); |
||||
|
i = i - 1; |
||||
|
dr.push(ds); |
||||
|
} |
||||
|
let ds = invert_keys(&kr[0], 0, 0); |
||||
|
dr.push(ds); |
||||
|
|
||||
|
let mut bs = xr; |
||||
|
while i < 8 { |
||||
|
// println!("Round {i}:");
|
||||
|
bs = idea_round(&dr[i], bs); |
||||
|
// println!("intermediate result: {:?}\n", bs.expand());
|
||||
|
i = i + 1; |
||||
|
} |
||||
|
let ys = idea_finish(&dr[8], bs); |
||||
|
ys.expand() |
||||
|
} |
||||
|
|
||||
|
#[cfg(test)] |
||||
|
#[macro_use] |
||||
|
extern crate quickcheck; |
||||
|
#[cfg(test)] |
||||
|
mod tests { |
||||
|
use super::{decrypt, encrypt}; |
||||
|
quickcheck! { |
||||
|
fn decrypt_encrypt(ks: u128, mes: u64) -> bool { |
||||
|
mes == decrypt(ks, encrypt(ks, mes)) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
use super::{slow_mul, mul}; |
||||
|
quickcheck! { |
||||
|
fn correct_mul(a: u16, b: u16) -> bool { |
||||
|
mul(a, b) == slow_mul(a, b) |
||||
|
} |
||||
|
} |
||||
|
} |
Binary file not shown.
Loading…
Reference in new issue