cipher-workshop/des/src/utils.rs

30 lines
1.2 KiB
Rust

/// Generic bit permutation for DES specification.
///
/// DES uses 1-based positioning where bit 1 is the leftmost (MSB) and bit 64 is the rightmost (LSB).
/// This function handles this correctly 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` - Table of 1-based positions (1 to `input_bits`) where each output bit comes from.
/// The table should have `output_bits` entries. For each entry i (0-based), `position_table`[i] indicates
/// which input bit (1-based) should go to the i-th output bit position (from MSB to LSB).
#[must_use]
pub fn permutate(
input: u64,
input_bit_amount: u64,
output_bit_amount: u64,
position_table: &[u8],
) -> u64 {
position_table
.iter()
.enumerate()
.fold(0, |acc, (idx, &input_pos_1based)| {
let input_bit_pos = input_bit_amount - u64::from(input_pos_1based);
let bit_value = (input >> input_bit_pos) & 1;
let output_bit_pos = output_bit_amount - 1 - (idx as u64);
acc | (bit_value << output_bit_pos)
})
}