mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
36 lines
1.2 KiB
Rust
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.
|
|
// Casting to u8 keeps the low byte, which is the half-block width here.
|
|
let r_u32 = r as u32;
|
|
let hash_val = ((r_u32.wrapping_mul(sub_key)) ^ (r_u32 >> 4)) as u8;
|
|
|
|
// 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)
|
|
}
|