mirror of
https://github.com/kristoferssolo/des-rs.git
synced 2025-12-20 11:04:38 +00:00
refactor: create permutation table applying function
This commit is contained in:
parent
5468d90a17
commit
a452149b33
85
src/lib.rs
85
src/lib.rs
@ -1,6 +1,6 @@
|
|||||||
mod constants;
|
mod constants;
|
||||||
|
|
||||||
use crate::constants::{PC1_TABLE, PC2_TABLE, PERMUTATION, ROUND_ROTATIONS};
|
use crate::constants::{IP, PC1_TABLE, PC2_TABLE, PERMUTATION, ROUND_ROTATIONS};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Des {
|
pub struct Des {
|
||||||
@ -54,8 +54,8 @@ impl Des {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn ip(&self, input: u64) -> u64 {
|
fn ip(&self, message: u64) -> u64 {
|
||||||
todo!()
|
apply_permutaion(message, 64, 64, &IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -75,23 +75,7 @@ impl Des {
|
|||||||
/// versus Rust u64's little-endian bit numbering (0-63, LSB first).
|
/// versus Rust u64's little-endian bit numbering (0-63, LSB first).
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn pc1(key: u64) -> u64 {
|
pub fn pc1(key: u64) -> u64 {
|
||||||
PC1_TABLE
|
apply_permutaion(key, 64, 56, &PC1_TABLE)
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.fold(0, |mut acc, (idx, &pos)| {
|
|
||||||
// pos is 1-based DES bit position (1-64, big-endian MSB first)
|
|
||||||
let des_bit_1based = u64::from(pos);
|
|
||||||
let des_bit_0based = des_bit_1based.saturating_sub(1); // 0-63
|
|
||||||
|
|
||||||
// Map DES big-endian position to u64 little-endian position
|
|
||||||
let bit_pos = 63u64.saturating_sub(des_bit_0based);
|
|
||||||
|
|
||||||
// Extract bit from u64 at the correct position
|
|
||||||
let bit = ((key >> bit_pos) & 1) << (55usize.saturating_sub(idx));
|
|
||||||
|
|
||||||
acc |= bit;
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compression permuation
|
/// Compression permuation
|
||||||
@ -100,23 +84,7 @@ pub fn pc1(key: u64) -> u64 {
|
|||||||
pub fn pc2(key: u64) -> u64 {
|
pub fn pc2(key: u64) -> u64 {
|
||||||
let key_56 = key & 0x00FF_FFFF_FFFF_FFFF;
|
let key_56 = key & 0x00FF_FFFF_FFFF_FFFF;
|
||||||
|
|
||||||
PC2_TABLE
|
apply_permutaion(key_56, 56, 48, &PC2_TABLE)
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.fold(0, |mut acc, (idx, &pos)| {
|
|
||||||
// pos is 1-based DES position in the 56-bit input (1-56)
|
|
||||||
let des_bit_1based = u64::from(pos);
|
|
||||||
let des_bit_0based = des_bit_1based.saturating_sub(1); // 0-55
|
|
||||||
|
|
||||||
// Map DES big-endian position to u64 little-endian position within 56 bits
|
|
||||||
let bit_pos = 55u64.saturating_sub(des_bit_0based);
|
|
||||||
|
|
||||||
// Extract bit from the 56-bit combined value
|
|
||||||
let bit = ((key_56 >> bit_pos) & 1) << (47usize.saturating_sub(idx));
|
|
||||||
|
|
||||||
acc |= bit;
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -177,6 +145,38 @@ fn generate_subkeys(key: u64) -> [u64; 16] {
|
|||||||
.expect("Exactly 16 subkeys expected")
|
.expect("Exactly 16 subkeys expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generic bit permutation for arbitrary input/output sizes.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// - `input` - The input value (treated as a bitfield of `input_bits` size)
|
||||||
|
/// - `input_bits` - Number of meaningful bits in the input (1-64)
|
||||||
|
/// - `output_bits` - Number of bits in the output (1-64)
|
||||||
|
/// - `position_table` - 1-based positions (1 to `input_bits`) where each output bit comes from
|
||||||
|
#[must_use]
|
||||||
|
fn apply_permutaion(input: u64, input_bits: u32, output_bits: u32, position_table: &[u8]) -> u64 {
|
||||||
|
position_table
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.fold(0, |acc, (idx, &pos)| {
|
||||||
|
// Convert 1-based DES position to 0-based input position (MSB first)
|
||||||
|
let pos_0based = u64::from(pos.saturating_sub(1));
|
||||||
|
let input_bit_pos = u64::from(input_bits)
|
||||||
|
.saturating_sub(1)
|
||||||
|
.saturating_sub(pos_0based);
|
||||||
|
|
||||||
|
// Extract bit from input
|
||||||
|
let bit_value = (input >> input_bit_pos) & 1;
|
||||||
|
|
||||||
|
// Extract bit from u64 at the correct position
|
||||||
|
let output_bit_pos = u64::from(output_bits)
|
||||||
|
.saturating_sub(1)
|
||||||
|
.saturating_sub(idx as u64);
|
||||||
|
let shifted_bit = bit_value << output_bit_pos;
|
||||||
|
|
||||||
|
acc | shifted_bit
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Encrypts data using ECB mode.
|
/// Encrypts data using ECB mode.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@ -287,11 +287,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
fn initial_permutation() {
|
fn initial_permutation() {
|
||||||
let expected_ip = 0xC2B093C7A3A7C24A;
|
let expected_ip = 0xCC00_CCFF_F0AA_F0AA;
|
||||||
let result = des_instance().ip(TEST_KEY);
|
let result = des_instance().ip(TEST_PLAINTEXT);
|
||||||
assert_eq!(result, expected_ip, "Initial permulation failed");
|
assert_eq!(
|
||||||
|
result, expected_ip,
|
||||||
|
"Initial permulation failed {result:016X} != {expected_ip:016X}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user