use crate::key_provider::{KeyMaterial, KeyProvider, KeyProviderError};
use async_trait::async_trait;
const FRAG_A: [u8; 8] = [0u8; 8];
const FRAG_B: [u8; 8] = [0u8; 8];
const FRAG_C: [u8; 8] = [0u8; 8];
const FRAG_D: [u8; 8] = [0u8; 8];
const TRANSFORM_MATRIX: [[u8; 4]; 4] = [[2, 5, 8, 3], [7, 9, 1, 4], [6, 2, 5, 8], [3, 7, 9, 1]];
const DECOY_DATA: [u8; 16] = [
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
];
const SBOX: [u8; 256] = generate_sbox();
const fn generate_sbox() -> [u8; 256] {
let mut sbox = [0u8; 256];
let mut i: usize = 0;
while i < 256 {
let mut v = i as u8;
v = v ^ v.rotate_left(1) ^ v.rotate_left(2) ^ v.rotate_left(3) ^ v.rotate_left(4) ^ 0x63;
sbox[i] = v;
i += 1;
}
sbox
}
const XOR_KEY_1: u8 = 0x5A;
const XOR_KEY_2: u8 = 0xA5;
const XOR_KEY_3: u8 = 0x3C;
const XOR_KEY_4: u8 = 0x7E;
pub struct WhiteBoxKeyProvider {
name: String,
}
impl WhiteBoxKeyProvider {
pub fn new(name: impl Into<String>) -> Self {
Self { name: name.into() }
}
pub fn with_default_name() -> Self {
Self::new("whitebox")
}
pub fn get_key(&self) -> Result<[u8; 32], KeyProviderError> {
self.reconstruct_key()
}
}
#[async_trait]
impl KeyProvider for WhiteBoxKeyProvider {
async fn provide(&self) -> Result<KeyMaterial, KeyProviderError> {
let key = self.reconstruct_key()?;
Ok(KeyMaterial::new(key, "whitebox_derived".to_string()))
}
fn provider_type(&self) -> &'static str {
"whitebox"
}
fn name(&self) -> &str {
&self.name
}
}
impl WhiteBoxKeyProvider {
fn reconstruct_key(&self) -> Result<[u8; 32], KeyProviderError> {
let mut raw = [0u8; 32];
for i in 0..8 {
raw[i] = FRAG_A[i] ^ XOR_KEY_1;
raw[i + 8] = FRAG_B[i] ^ XOR_KEY_2;
raw[i + 16] = FRAG_C[i] ^ XOR_KEY_3;
raw[i + 24] = FRAG_D[i] ^ XOR_KEY_4;
}
for chunk in raw.chunks_mut(4) {
let block: [u8; 4] = chunk.try_into().unwrap();
let transformed = Self::transform_block(&block);
chunk.copy_from_slice(&transformed);
}
Self::final_diffusion(&mut raw);
Self::verify_key(&raw)?;
Ok(raw)
}
fn transform_block(block: &[u8; 4]) -> [u8; 4] {
let mut result = [0u8; 4];
for i in 0..4 {
for j in 0..4 {
result[i] ^= Self::galois_mul(block[j], TRANSFORM_MATRIX[i][j]);
}
}
result
}
#[inline(always)]
fn galois_mul(a: u8, b: u8) -> u8 {
let mut p: u8 = 0;
let mut a = a;
let mut b = b;
for _ in 0..8 {
if b & 1 != 0 {
p ^= a;
}
let hi_bit = a & 0x80;
a <<= 1;
if hi_bit != 0 {
a ^= 0x1B;
}
b >>= 1;
}
p
}
#[inline(always)]
fn rotate_left(value: u8, n: u8) -> u8 {
value.rotate_left(n.into())
}
fn final_diffusion(key: &mut [u8; 32]) {
for i in 0..32 {
key[i] = SBOX[key[i] as usize];
key[i] = Self::rotate_left(key[i], 3);
if i > 0 {
key[i] ^= key[i - 1];
}
}
for i in 0..16 {
key[i] ^= DECOY_DATA[i];
key[i + 16] ^= DECOY_DATA[i];
}
}
fn verify_key(_key: &[u8; 32]) -> Result<(), KeyProviderError> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_reconstruction_deterministic() {
let provider = WhiteBoxKeyProvider::new("test");
let key1 = provider.reconstruct_key().unwrap();
let key2 = provider.reconstruct_key().unwrap();
assert_eq!(key1, key2, "key reconstruction should be deterministic");
}
#[test]
fn test_key_providers_same_key() {
let p1 = WhiteBoxKeyProvider::new("p1");
let p2 = WhiteBoxKeyProvider::new("p2");
let k1 = p1.reconstruct_key().unwrap();
let k2 = p2.reconstruct_key().unwrap();
assert_eq!(k1, k2, "same fragments should produce same key");
}
#[test]
fn test_key_length() {
let provider = WhiteBoxKeyProvider::new("test");
let key = provider.reconstruct_key().unwrap();
assert_eq!(key.len(), 32, "AES-256 requires 32 bytes");
}
}