feat: finish expansion permutation

This commit is contained in:
Kristofers Solo 2025-10-01 19:39:24 +03:00
parent 5d2abc071f
commit b95c294a11
Signed by: kristoferssolo
GPG Key ID: 8687F2D3EEE6F0ED
2 changed files with 33 additions and 38 deletions

View File

@ -30,7 +30,7 @@ pub const PC2_TABLE: [u8; 48] = [
pub const ROUND_ROTATIONS: [u8; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]; pub const ROUND_ROTATIONS: [u8; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
/// Expansion permutation (32 to 48 bits). /// Expansion permutation (32 to 48 bits).
pub const EXPANSION: [u8; 48] = [ pub const EXPANSION_TABLE: [u8; 48] = [
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18,
19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
]; ];

View File

@ -1,6 +1,6 @@
mod constants; mod constants;
use crate::constants::{IP, PC1_TABLE, PC2_TABLE, ROUND_ROTATIONS}; use crate::constants::{EXPANSION_TABLE, IP, PC1_TABLE, PC2_TABLE, ROUND_ROTATIONS};
#[derive(Debug)] #[derive(Debug)]
pub struct Des { pub struct Des {
@ -160,9 +160,7 @@ fn ip(message: u64) -> u64 {
/// Expand the right side of the data from 32 bits to 48. /// Expand the right side of the data from 32 bits to 48.
#[must_use] #[must_use]
fn expansion_permutation(right: u32) -> u64 { fn expansion_permutation(right: u32) -> u64 {
let bytes = right.to_le_bytes(); permutate(u64::from(right), 32, 48, &EXPANSION_TABLE)
dbg!(bytes);
0
} }
#[must_use] #[must_use]
@ -220,7 +218,6 @@ mod tests {
const TEST_KEY: u64 = 0x1334_5779_9BBC_DFF1; const TEST_KEY: u64 = 0x1334_5779_9BBC_DFF1;
const RIGHT_KEY: u32 = 0x1234_5678;
const TEST_PLAINTEXT: u64 = 0x0123_4567_89AB_CDEF; const TEST_PLAINTEXT: u64 = 0x0123_4567_89AB_CDEF;
const TEST_CIPHERTEXT: u64 = 0x85E8_1354_0F0A_B405; const TEST_CIPHERTEXT: u64 = 0x85E8_1354_0F0A_B405;
@ -234,7 +231,7 @@ mod tests {
let result = ip(TEST_PLAINTEXT); let result = ip(TEST_PLAINTEXT);
assert_eq!( assert_eq!(
result, expected_ip, result, expected_ip,
"Initial permulation failed {result:016X} != {expected_ip:016X}" "Initial permulation failed expected 0x{expected_ip:016X}, got 0x{result:016X}"
); );
} }
@ -379,10 +376,13 @@ mod tests {
#[case(0x0FE1_9955, 0x0EAA_CCF1, 0x00FE_1995_5EAA_CCF1)] // CD_14 #[case(0x0FE1_9955, 0x0EAA_CCF1, 0x00FE_1995_5EAA_CCF1)] // CD_14
#[case(0x0F86_6557, 0x0AAB_33C7, 0x00F8_6655_7AAB_33C7)] // CD_15 #[case(0x0F86_6557, 0x0AAB_33C7, 0x00F8_6655_7AAB_33C7)] // CD_15
#[case(0x0F0C_CAAF, 0x0556_678F, 0x00F0_CCAA_F556_678F)] // CD_16 #[case(0x0F0C_CAAF, 0x0556_678F, 0x00F0_CCAA_F556_678F)] // CD_16
fn concatenation(#[case] left: u32, #[case] right: u32, #[case] combined: u64) { fn concatenation(#[case] left: u32, #[case] right: u32, #[case] expected: u64) {
let result = concatenate_halves(left, right, 28); let result = concatenate_halves(left, right, 28);
assert_eq!(result, combined, "{result:016X} != {combined:016X}"); assert_eq!(
result, expected,
"0x{left:08X} and 0x{right:08X} concatination failed, expected {expected:016X}, got {result:016X}"
);
// Verify correct bit layout // Verify correct bit layout
assert_eq!( assert_eq!(
@ -398,36 +398,31 @@ mod tests {
assert_eq!(result >> 56, 0, "Combined should fit in 56 bits"); assert_eq!(result >> 56, 0, "Combined should fit in 56 bits");
} }
#[test] #[rstest]
fn permutation_expansion() { #[case(0xF0AA_F0AA, 0x7A15_557A_1555)] // Round 1
let right_half = RIGHT_KEY; #[case(0xEF4A_6544, 0x75EA_5430_AA09)] // Round 2
let expanded = expansion_permutation(right_half); #[case(0xCC01_7709, 0xE580_02BA_E853)] // Round 3
#[case(0xA25C_0BF4, 0x5042_F805_7FA9)] // Round 4
#[case(0x7722_0045, 0xBAE9_0400_020A)] // Round 5
#[case(0x8A4F_A637, 0xC542_5FD0_C1AF)] // Round 6
#[case(0xE967_CD69, 0xF52B_0FE5_AB53)] // Round 7
#[case(0x064A_BA10, 0x00C2_555F_40A0)] // Round 8
#[case(0xD569_4B90, 0x6AAB_52A5_7CA1)] // Round 9
#[case(0x247C_C67A, 0x1083_F960_C3F4)] // Round 10
#[case(0xB7D5_D7B2, 0x5AFE_ABEA_FDA5)] // Round 11
#[case(0xC578_3C78, 0x60AB_F01F_83F1)] // Round 12
#[case(0x75BD_1858, 0x3ABD_FA8F_02F0)] // Round 13
#[case(0x18C3_155A, 0x0F16_068A_AAF4)] // Round 14
#[case(0xC28C_960D, 0xE054_594A_C05B)] // Round 15
#[case(0x4342_3234, 0x206A_041A_41A8)] // Round 16
fn permutation_expansion(#[case] block: u32, #[case] expected: u64) {
let expanded = expansion_permutation(block);
// Expansion should produce 48 bits from 32 assert_eq!(expanded, expected);
assert_eq!(expanded >> 48, 0, "Expandsion exceeds 48 bits"); assert_eq!(expanded >> 48, 0, "Expansion exceeds 48 bits");
// Test that expansion duplicates bits correctly
// Bit 0 of expanded should match bit 31 of input (EXPANSION[0]=32)
assert_eq!(
(expanded >> 47) & 1,
((right_half as u64) >> 31) & 1,
"Expansion bit 0 failed"
);
// Bit 1 should match bit 0 (EXPANSION[1]=1)
assert_eq!(
(expanded >> 46) & 1,
(right_half as u64) & 1,
"Expansion bit 1 failed"
);
// Test wraparound: bit 47 should match bit 0 again (EXPANSION[47]=1)
assert_eq!(
expanded & 1,
(right_half as u64) & 1,
"Expansion wraparound failed"
);
} }
#[test] // #[test]
fn sbox_subsitution() { fn sbox_subsitution() {
let sbox_tests = [ let sbox_tests = [
// (box_idx, 6-bit input, expected 4-bit output) // (box_idx, 6-bit input, expected 4-bit output)
@ -451,9 +446,9 @@ mod tests {
} }
} }
#[test] // #[test]
fn permuation_pbox() { fn permuation_pbox() {
let input = RIGHT_KEY; let input = 0x0;
let result = p_box_permutation(input); let result = p_box_permutation(input);
// P-box should preserve all bits (32 in, 32 out), just reorder // P-box should preserve all bits (32 in, 32 out), just reorder