use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main() {
let sbox = generate_sbox();
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set by Cargo");
let dest_path = Path::new(&out_dir).join("sbox.rs");
let mut f = File::create(&dest_path).expect("Failed to create S-box output file");
writeln!(f, "/// S-box substitution table (256 bytes)")
.expect("Failed to write S-box header comment");
writeln!(f, "///").expect("Failed to write S-box comment line");
writeln!(f, "/// Auto-generated at compile time using: ROTL8(floor(256 * frac(sin(i+1))), i mod 8) ^ 0x9E")
.expect("Failed to write S-box generation formula comment");
writeln!(
f,
"/// This provides nonlinear substitution for the ClockMix operation."
)
.expect("Failed to write S-box purpose comment");
writeln!(f, "pub const SBOX: [u8; 256] = [").expect("Failed to write S-box array start");
for (i, &val) in sbox.iter().enumerate() {
if i % 16 == 0 {
write!(f, " ").expect("Failed to write S-box indentation");
}
write!(f, "0x{:02X},", val).expect("Failed to write S-box value");
if (i + 1) % 16 == 0 {
writeln!(f).expect("Failed to write S-box line break");
} else {
write!(f, " ").expect("Failed to write S-box space separator");
}
}
writeln!(f, "];").expect("Failed to write S-box array end");
println!("cargo:rerun-if-changed=build.rs");
}
fn generate_sbox() -> [u8; 256] {
let mut sbox = [0u8; 256];
let mask = 0x9Eu8;
for (i, item) in sbox.iter_mut().enumerate() {
let sin_val = ((i + 1) as f64).sin();
let frac = sin_val - sin_val.floor();
let base = (frac * 256.0).floor() as u8;
let rot = (i % 8) as u8;
let rotated = rotl8(base, rot);
*item = rotated ^ mask;
}
sbox
}
fn rotl8(x: u8, n: u8) -> u8 {
let n = n & 7;
if n == 0 {
x
} else {
(x << n) | (x >> (8u8.wrapping_sub(n)))
}
}