Files
unshell/src/crypto/feistel.rs
T
2026-05-31 14:47:25 -06:00

36 lines
1.2 KiB
Rust

/// Performs a deterministic pseudo-random shuffle of a 16-bit index.
///
/// # Arguments
/// * `index` - The input value (0..65536).
/// * `seed` - The 32-bit seed acting as the encryption key.
///
/// # Returns
/// A unique 16-bit shuffled value.
pub fn feistel_shuffle(index: u16, seed: u32) -> u16 {
// Split 16-bit index into two 8-bit halves
let mut l = ((index >> 8) & 0xFF) as u8;
let mut r = (index & 0xFF) as u8;
// Perform 4 rounds of Feistel mixing
for round in 0..4 {
// Derive sub-key: Rotate seed and add golden ratio constant
let rot_amount = (round * 5) % 32;
let sub_key = seed
.rotate_left(rot_amount)
.wrapping_add(round.wrapping_mul(0x9E3779B9));
// Round function F: Simple multiplicative hash mixing R and sub_key
// We cast to u32 for multiplication to avoid overflow, then mask back to 8 bits
let r_u32 = r as u32;
let hash_val = ((r_u32.wrapping_mul(sub_key)) ^ (r_u32 >> 4)) as u8 & 0xFF;
// Feistel step: New L = Old R, New R = Old L XOR F(R, key)
let temp = l;
l = r;
r = temp ^ hash_val;
}
// Recombine halves
((l as u16) << 8) | (r as u16)
}