use crate::{Point3D, RotationAxis};
use chacha20poly1305::{
aead::{Aead, KeyInit, OsRng},
ChaCha20Poly1305, Nonce,
};
use rand::RngCore;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Spha256 {
point: Point3D,
rotation_axis: RotationAxis,
iterations: u32,
strength: f64,
}
impl Spha256 {
pub fn new(
point: Point3D,
rotation_axis: RotationAxis,
iterations: u32,
strength: f64,
) -> Self {
Spha256 {
point,
rotation_axis,
iterations,
strength,
}
}
fn generate_key(&self) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(&self.point.x.to_bits().to_ne_bytes());
hasher.update(&self.point.y.to_bits().to_ne_bytes());
hasher.update(&self.point.z.to_bits().to_ne_bytes());
hasher.update(&self.rotation_axis.x.to_bits().to_ne_bytes());
hasher.update(&self.rotation_axis.y.to_bits().to_ne_bytes());
hasher.update(&self.rotation_axis.z.to_bits().to_ne_bytes());
hasher.update(&self.iterations.to_ne_bytes());
hasher.update(&self.strength.to_bits().to_ne_bytes());
let result = hasher.finalize();
let mut key = [0u8; 32];
key.copy_from_slice(&result[..32]);
key
}
pub fn encrypt(&self, data: &[u8]) -> Vec<u8> {
let key = self.generate_key();
let cipher = ChaCha20Poly1305::new(&key.into());
let mut nonce_bytes = [0u8; 12];
OsRng.fill_bytes(&mut nonce_bytes);
let nonce = Nonce::from_slice(&nonce_bytes);
let ciphertext = cipher.encrypt(nonce, data).expect("Encryption failed");
let mut encrypted = Vec::with_capacity(nonce_bytes.len() + ciphertext.len());
encrypted.extend_from_slice(&nonce_bytes);
encrypted.extend_from_slice(&ciphertext);
encrypted
}
pub fn decrypt(&self, encrypted: &[u8]) -> Result<Vec<u8>, &'static str> {
if encrypted.len() < 12 {
return Err("Ciphertext too short to contain nonce");
}
let (nonce_bytes, ciphertext) = encrypted.split_at(12);
let nonce = Nonce::from_slice(nonce_bytes);
let key = self.generate_key();
let cipher = ChaCha20Poly1305::new(&key.into());
let plaintext = cipher
.decrypt(nonce, ciphertext)
.map_err(|_| "Decryption failed")?;
Ok(plaintext)
}
}