use crate::error::{Error, Result};
use object::{Object, ObjectSection};
use sha2::{Digest, Sha256};
include!(concat!(env!("OUT_DIR"), "/crypto_constants.rs"));
pub fn xor_cipher(data: &[u8], key: &[u8]) -> Vec<u8> {
data.iter()
.enumerate()
.map(|(i, &b)| b ^ key[i % key.len()])
.collect()
}
pub fn obfuscate(data: &[u8], seed: u8) -> Vec<u8> {
let mut result: Vec<u8> = data
.iter()
.enumerate()
.map(|(i, &b)| {
let mut byte = b;
byte = byte.rotate_left(ROTATION_BITS);
byte = OBFUSCATE_TABLE[byte as usize];
byte = byte
.wrapping_mul(OBFUSCATE_MULTIPLIER)
.wrapping_add(OBFUSCATE_BASE)
.wrapping_add(seed)
.wrapping_add(i as u8);
byte ^= XOR_MASK;
byte
})
.collect();
for round in 0..EXTRA_ROUNDS {
result = result
.iter()
.enumerate()
.map(|(i, &b)| {
b.wrapping_add((round as u8).wrapping_mul(seed))
.wrapping_add(i as u8)
})
.collect();
}
result
}
pub fn deobfuscate(data: &[u8], seed: u8) -> Vec<u8> {
let mut result = data.to_vec();
for round in (0..EXTRA_ROUNDS).rev() {
result = result
.iter()
.enumerate()
.map(|(i, &b)| {
b.wrapping_sub(i as u8)
.wrapping_sub((round as u8).wrapping_mul(seed))
})
.collect();
}
result
.iter()
.enumerate()
.map(|(i, &b)| {
let mut byte = b;
byte ^= XOR_MASK;
byte = byte
.wrapping_sub(i as u8)
.wrapping_sub(seed)
.wrapping_sub(OBFUSCATE_BASE);
let inv_multiplier = mod_inverse(OBFUSCATE_MULTIPLIER);
byte = byte.wrapping_mul(inv_multiplier);
byte = DEOBFUSCATE_TABLE[byte as usize];
byte = byte.rotate_right(ROTATION_BITS);
byte
})
.collect()
}
fn mod_inverse(a: u8) -> u8 {
let mut t = 0i32;
let mut new_t = 1i32;
let mut r = 256i32;
let mut new_r = a as i32;
while new_r != 0 {
let quotient = r / new_r;
let tmp_t = t;
t = new_t;
new_t = tmp_t - quotient * new_t;
let tmp_r = r;
r = new_r;
new_r = tmp_r - quotient * new_r;
}
if t < 0 {
t += 256;
}
t as u8
}
pub fn derive_key_from_section(
binary_data: &[u8],
section_name: &str,
key_len: usize,
) -> Result<Vec<u8>> {
let obj_file = object::File::parse(binary_data)
.map_err(|e| Error::Parse(format!("无法解析二进制格式: {}", e)))?;
for section in obj_file.sections() {
if let Ok(name) = section.name() {
if name == section_name {
if let Ok(data) = section.data() {
let mut hasher = Sha256::new();
hasher.update(data);
let hash = hasher.finalize();
return Ok(hash[..key_len.min(32)].to_vec());
}
}
}
}
Err(Error::SectionNotFound(section_name.to_string()))
}
pub fn encrypt_shard(data: &[u8], derive_key: &[u8], seed: u8) -> Vec<u8> {
let obfuscated = obfuscate(data, seed);
xor_cipher(&obfuscated, derive_key)
}
pub fn decrypt_shard(encrypted_data: &[u8], derive_key: &[u8], seed: u8) -> Vec<u8> {
let xor_decrypted = xor_cipher(encrypted_data, derive_key);
deobfuscate(&xor_decrypted, seed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_xor_cipher() {
let data = b"hello world";
let key = b"secret";
let encrypted = xor_cipher(data, key);
assert_ne!(data, encrypted.as_slice());
let decrypted = xor_cipher(&encrypted, key);
assert_eq!(data, decrypted.as_slice());
}
#[test]
fn test_obfuscate() {
let data = b"test data 12345";
let seed = 42;
let obfuscated = obfuscate(data, seed);
assert_ne!(data, obfuscated.as_slice());
let deobfuscated = deobfuscate(&obfuscated, seed);
assert_eq!(data, deobfuscated.as_slice());
}
#[test]
fn test_encrypt_decrypt_shard() {
let original = b"my secret key";
let derive_key = b"derived_key_from_hash";
let seed = 123;
let encrypted = encrypt_shard(original, derive_key, seed);
assert_ne!(original, encrypted.as_slice());
let decrypted = decrypt_shard(&encrypted, derive_key, seed);
assert_eq!(original, decrypted.as_slice());
}
#[test]
fn test_different_seeds_produce_different_results() {
let data = b"same data";
let key = b"same key";
let encrypted1 = encrypt_shard(data, key, 1);
let encrypted2 = encrypt_shard(data, key, 2);
assert_ne!(encrypted1, encrypted2);
}
#[test]
fn test_empty_data() {
let data = b"";
let key = b"key";
let seed = 1;
let encrypted = encrypt_shard(data, key, seed);
assert_eq!(encrypted.len(), 0);
let decrypted = decrypt_shard(&encrypted, key, seed);
assert_eq!(data, decrypted.as_slice());
}
#[test]
fn test_large_data() {
let data = vec![42u8; 10000];
let key = b"test_key";
let seed = 99;
let encrypted = encrypt_shard(&data, key, seed);
assert_eq!(encrypted.len(), data.len());
let decrypted = decrypt_shard(&encrypted, key, seed);
assert_eq!(data, decrypted);
}
}