Skip to content

Commit

Permalink
reorganized twofish functions
Browse files Browse the repository at this point in the history
  • Loading branch information
SymmetricChaos committed Oct 19, 2024
1 parent db22981 commit e0cf67d
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 78 deletions.
30 changes: 11 additions & 19 deletions ciphers/src/digital/block_ciphers/twofish/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,23 @@ pub const QORD: [[usize; 5]; 4] = [
[1, 0, 1, 1, 0],
];

pub(super) fn q0(n: u8) -> u8 {
pub(super) fn q(v: usize, n: u8) -> u8 {
let a0 = (n >> 4) & 15;
let b0 = n & 15;
let a1 = a0 ^ b0;
let b1 = a0 ^ ((b0 << 3) | (b0 >> 1)) ^ ((a0 << 3) & 15); // Because the upper 4 bits will be empty the rotation of the lower 4 bits of b0 is always correct
let a2 = Q0[0][a1 as usize];
let b2 = Q0[1][b1 as usize];
let (a2, b2) = if v == 0 {
(Q0[0][a1 as usize], Q0[1][b1 as usize])
} else {
(Q1[0][a1 as usize], Q1[1][b1 as usize])
};
let a3 = a2 ^ b2;
let b3 = a2 ^ ((b2 << 3) | (b2 >> 1)) ^ ((a2 << 3) & 15); // As for b0
let a4 = Q0[2][a3 as usize];
let b4 = Q0[3][b3 as usize];
(b4 << 4) | a4
}

pub(super) fn q1(n: u8) -> u8 {
let a0 = (n >> 4) & 15;
let b0 = n & 15;
let a1 = a0 ^ b0;
let b1 = a0 ^ ((b0 << 3) | (b0 >> 1)) ^ ((8 * a0) & 15);
let a2 = Q1[0][a1 as usize];
let b2 = Q1[1][b1 as usize];
let a3 = a2 ^ b2;
let b3 = a2 ^ ((b2 << 3) | (b2 >> 1)) ^ ((8 * a2) & 15);
let a4 = Q1[2][a3 as usize];
let b4 = Q1[3][b3 as usize];
let (a4, b4) = if v == 0 {
(Q0[0][a3 as usize], Q0[1][b3 as usize])
} else {
(Q1[0][a3 as usize], Q1[1][b3 as usize])
};
(b4 << 4) | a4
}

Expand Down
154 changes: 95 additions & 59 deletions ciphers/src/digital/block_ciphers/twofish/twofish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,13 @@ use utils::byte_formatting::{fill_u32s_le, u32s_to_bytes_le, ByteFormat};

use super::{
super::block_cipher::{BCMode, BCPadding, BlockCipher},
functions::{mds_mult, pht, q0, q1},
functions::{mds_column_mult, mds_mult, pht, q, QORD},
};

fn h(x: u32, list: &[u8], offset: usize) -> u32 {
let mut y = x.to_le_bytes();
if K == 4 {
y[0] = q1(y[0]) ^ list[4 * (6 + offset + 0)];
y[1] = q0(y[1]) ^ list[4 * (6 + offset + 1)];
y[2] = q0(y[2]) ^ list[4 * (6 + offset + 2)];
y[3] = q1(y[3]) ^ list[4 * (6 + offset + 3)];
}

if K >= 3 {
y[0] = q1(y[0]) ^ list[4 * (4 + offset + 0)];
y[1] = q1(y[1]) ^ list[4 * (4 + offset + 1)];
y[2] = q0(y[2]) ^ list[4 * (4 + offset + 2)];
y[3] = q0(y[3]) ^ list[4 * (4 + offset + 3)];
}

let a = 4 * (2 + offset);
let b = 4 * offset;

y[0] = q1(q0(q0(y[0]) ^ list[a + 0]) ^ list[b + 0]);
y[1] = q0(q1(q1(y[1]) ^ list[a + 1]) ^ list[b + 1]);
y[2] = q1(q1(q0(y[2]) ^ list[a + 2]) ^ list[b + 2]);
y[3] = q0(q1(q1(y[3]) ^ list[a + 3]) ^ list[b + 3]);

mds_mult(y)
}

fn g(n: u32) -> u32 {
let mut out = 0;
let mut x = n.to_le_bytes();

for i in 0..4 {}

out
}

fn f(a: u32, b: u32, round: usize, subkeys: &[u32; 40]) -> (u32, u32) {
let t0 = g(a);
let t1 = g(b.rotate_left(8));
let mut o = pht(t0, t1);
o.0 = o.0.wrapping_add(subkeys[2 * round + 8]);
o.1 = o.1.wrapping_add(subkeys[2 * round + 9]);
o
}

const KEY_BYTES: usize = 16;
const KEY_WORDS: usize = KEY_BYTES / 4;
const K: usize = 2; // Keylength in bits divided by 64
const START: usize = 2;
const K: usize = KEY_BYTES / 8; // Keylength in bits divided by 64
const START: usize = (K + 2) - 4;

pub struct TwoFish128 {
pub input_format: ByteFormat,
Expand All @@ -63,7 +18,8 @@ pub struct TwoFish128 {
pub padding: BCPadding,
pub iv: u128,
pub subkeys: [u32; 40],
sboxes: [[u32; 256]; 4],
pub sbox_key: [u8; 16],
// sboxes: [[u32; 256]; 4],
}

impl Default for TwoFish128 {
Expand All @@ -75,16 +31,68 @@ impl Default for TwoFish128 {
padding: BCPadding::default(),
iv: 0,
subkeys: [0; 40],
sboxes: [[0; 256]; 4],
sbox_key: [0; 16],
// sboxes: [[0; 256]; 4],
}
}
}

crate::block_cipher_builders! {TwoFish128, u128}

impl TwoFish128 {
pub fn sbox(&self, n: u32, i: usize) -> u32 {
self.sboxes[i][n as usize]
// pub fn sbox(&self, n: u32, i: usize) -> u32 {
// self.sboxes[i][n as usize]
// }

fn h(x: u32, list: &[u8], offset: usize) -> u32 {
let mut y = x.to_le_bytes();
if K == 4 {
y[0] = q(1, y[0]) ^ list[4 * (6 + offset + 0)];
y[1] = q(0, y[1]) ^ list[4 * (6 + offset + 1)];
y[2] = q(0, y[2]) ^ list[4 * (6 + offset + 2)];
y[3] = q(1, y[3]) ^ list[4 * (6 + offset + 3)];
}

if K >= 3 {
y[0] = q(1, y[0]) ^ list[4 * (4 + offset + 0)];
y[1] = q(1, y[1]) ^ list[4 * (4 + offset + 1)];
y[2] = q(0, y[2]) ^ list[4 * (4 + offset + 2)];
y[3] = q(0, y[3]) ^ list[4 * (4 + offset + 3)];
}

let a = 4 * (2 + offset);
let b = 4 * offset;

y[0] = q(1, q(0, q(0, y[0]) ^ list[a + 0]) ^ list[b + 0]);
y[1] = q(0, q(1, q(1, y[1]) ^ list[a + 1]) ^ list[b + 1]);
y[2] = q(1, q(1, q(0, y[2]) ^ list[a + 2]) ^ list[b + 2]);
y[3] = q(0, q(1, q(1, y[3]) ^ list[a + 3]) ^ list[b + 3]);

mds_mult(y)
}

fn g(&self, x: u32) -> u32 {
let mut out: u32 = 0;
for y in 0..4 {
let mut g = q(QORD[y][START], (x >> (8 * y)) as u8);

for z in START + 1..5 {
g ^= self.sbox_key[4 * (z - START - 1) + y];
g = q(QORD[y][z], g);
}

out ^= mds_column_mult(g, y);
}
out
}

fn f(&self, a: u32, b: u32, round: usize) -> (u32, u32) {
let t0 = self.g(a);
let t1 = self.g(b.rotate_left(8));
let mut o = pht(t0, t1);
o.0 = o.0.wrapping_add(self.subkeys[2 * round + 8]);
o.1 = o.1.wrapping_add(self.subkeys[2 * round + 9]);
o
}

pub fn ksa(&mut self, bytes: [u8; KEY_BYTES]) {
Expand Down Expand Up @@ -120,11 +128,25 @@ impl BlockCipher<16> for TwoFish128 {
block[i] ^= self.subkeys[i]
}

for i in 0..8 {}
for i in 0..8 {
let k = 4 * i + 8;

let t1 = self.g(block[1].rotate_left(8));
let t0 = self.g(block[0]).wrapping_add(t1);
block[2] = (block[2] ^ (t0.wrapping_add(self.subkeys[k]))).rotate_right(1);
let t2 = t1.wrapping_add(t0).wrapping_add(self.subkeys[k + 1]);
block[3] = block[3].rotate_left(1) ^ t2;

let t1 = self.g(block[3].rotate_left(8));
let t0 = self.g(block[2]).wrapping_add(t1);
block[0] = (block[0] ^ (t0.wrapping_add(self.subkeys[k + 2]))).rotate_right(1);
let t2 = t1.wrapping_add(t0).wrapping_add(self.subkeys[k + 3]);
block[1] = (block[1].rotate_left(1)) ^ t2;
}

// Output Whitening
for i in 4..8 {
block[i - 4] ^= self.subkeys[i]
block[i - 4] ^= self.subkeys[i];
}

u32s_to_bytes_le(bytes, &block);
Expand All @@ -135,15 +157,29 @@ impl BlockCipher<16> for TwoFish128 {
fill_u32s_le(&mut block, bytes);

// Input Whitening
for i in 0..4 {
block[i] ^= self.subkeys[i]
for i in 4..8 {
block[i - 4] ^= self.subkeys[i]
}

for i in (0..8).rev() {}
for i in (0..8).rev() {
let k = 4 * i + 8;

let t1 = self.g(block[3].rotate_left(8));
let t0 = self.g(block[2]).wrapping_add(t1);
block[0] = (block[0] ^ (t0.wrapping_add(self.subkeys[k]))).rotate_right(1);
let t2 = t1.wrapping_add(t0).wrapping_add(self.subkeys[k + 1]);
block[1] = block[1].rotate_left(1) ^ t2;

let t1 = self.g(block[1].rotate_left(8));
let t0 = self.g(block[0]).wrapping_add(t1);
block[2] = (block[2] ^ (t0.wrapping_add(self.subkeys[k + 2]))).rotate_right(1);
let t2 = t1.wrapping_add(t0).wrapping_add(self.subkeys[k + 3]);
block[3] = (block[3].rotate_left(1)) ^ t2;
}

// Output Whitening
for i in 4..8 {
block[i - 4] ^= self.subkeys[i]
for i in 0..4 {
block[i] ^= self.subkeys[i]
}

u32s_to_bytes_le(bytes, &block);
Expand Down

0 comments on commit e0cf67d

Please sign in to comment.