Files
unshell/src/crypto/feistel.rs
T

36 lines
1.2 KiB
Rust
Raw Normal View History

2026-05-31 13:22:02 -06:00
/// 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));
2026-06-01 09:54:37 -06:00
// Round function F: Simple multiplicative hash mixing R and sub_key.
// Casting to u8 keeps the low byte, which is the half-block width here.
2026-05-31 13:22:02 -06:00
let r_u32 = r as u32;
2026-06-01 09:54:37 -06:00
let hash_val = ((r_u32.wrapping_mul(sub_key)) ^ (r_u32 >> 4)) as u8;
2026-05-31 13:22:02 -06:00
// 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)
}