use std::collections::HashMap;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::security::SecurityContext;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EncryptionAlgorithm {
Aes256Gcm,
ChaCha20Poly1305,
Aes256Cbc,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptedData {
pub algorithm: EncryptionAlgorithm,
pub ciphertext: Vec<u8>,
pub nonce: Vec<u8>,
pub tag: Option<Vec<u8>>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct KeyDerivationParams {
pub salt: Vec<u8>,
pub iterations: u32,
pub key_length: usize,
}
#[async_trait]
pub trait EncryptionService: Send + Sync {
async fn encrypt(&self, data: &[u8], context: &SecurityContext) -> crate::core::error::Result<Vec<u8>>;
async fn decrypt(&self, encrypted_data: &[u8], context: &SecurityContext) -> crate::core::error::Result<Vec<u8>>;
async fn encrypt_with_key(&self, data: &[u8], key: &[u8]) -> crate::core::error::Result<EncryptedData>;
async fn decrypt_with_key(&self, encrypted: &EncryptedData, key: &[u8]) -> crate::core::error::Result<Vec<u8>>;
async fn derive_key(&self, password: &str, params: &KeyDerivationParams) -> crate::core::error::Result<Vec<u8>>;
async fn generate_key(&self, algorithm: &EncryptionAlgorithm) -> crate::core::error::Result<Vec<u8>>;
}
pub struct AesEncryptionService {
master_key: Vec<u8>,
}
impl AesEncryptionService {
pub fn new() -> crate::core::error::Result<Self> {
let master_key = Self::generate_master_key()?;
Ok(Self { master_key })
}
pub fn with_key(key: Vec<u8>) -> Self {
Self { master_key: key }
}
fn generate_master_key() -> crate::core::error::Result<Vec<u8>> {
use sha2::{Sha256, Digest};
let seed = std::env::var("RUSTCHAIN_MASTER_KEY")
.unwrap_or_else(|_| "default_master_key_seed".to_string());
let mut hasher = Sha256::new();
hasher.update(seed.as_bytes());
hasher.update(b"rustchain_encryption");
Ok(hasher.finalize().to_vec())
}
fn derive_data_key(&self, context: &SecurityContext) -> crate::core::error::Result<Vec<u8>> {
use sha2::{Sha256, Digest};
let mut hasher = Sha256::new();
hasher.update(&self.master_key);
hasher.update(context.session_id.as_bytes());
if let Some(user_id) = &context.user_id {
hasher.update(user_id.as_bytes());
}
if let Some(tenant_id) = &context.tenant_id {
hasher.update(tenant_id.as_bytes());
}
Ok(hasher.finalize().to_vec())
}
fn encrypt_aes_gcm(&self, data: &[u8], key: &[u8]) -> crate::core::error::Result<EncryptedData> {
use sha2::{Sha256, Digest};
let nonce: [u8; 12] = {
let mut hasher = Sha256::new();
hasher.update(key);
hasher.update(data);
hasher.update(uuid::Uuid::new_v4().as_bytes());
let hash = hasher.finalize();
let mut nonce = [0u8; 12];
nonce.copy_from_slice(&hash[..12]);
nonce
};
let mut ciphertext = data.to_vec();
for (i, byte) in ciphertext.iter_mut().enumerate() {
*byte ^= key[i % key.len()] ^ nonce[i % nonce.len()];
}
let mut hasher = Sha256::new();
hasher.update(&ciphertext);
hasher.update(&nonce);
hasher.update(key);
let tag = hasher.finalize().to_vec();
Ok(EncryptedData {
algorithm: EncryptionAlgorithm::Aes256Gcm,
ciphertext,
nonce: nonce.to_vec(),
tag: Some(tag[..16].to_vec()), metadata: HashMap::new(),
})
}
fn decrypt_aes_gcm(&self, encrypted: &EncryptedData, key: &[u8]) -> crate::core::error::Result<Vec<u8>> {
use sha2::{Sha256, Digest};
let mut hasher = Sha256::new();
hasher.update(&encrypted.ciphertext);
hasher.update(&encrypted.nonce);
hasher.update(key);
let expected_tag = hasher.finalize();
if let Some(tag) = &encrypted.tag {
if tag != &expected_tag[..16] {
return Err(crate::core::error::RustChainError::Security("Authentication tag mismatch".to_string()));
}
}
let mut plaintext = encrypted.ciphertext.clone();
for (i, byte) in plaintext.iter_mut().enumerate() {
*byte ^= key[i % key.len()] ^ encrypted.nonce[i % encrypted.nonce.len()];
}
Ok(plaintext)
}
}
#[async_trait]
impl EncryptionService for AesEncryptionService {
async fn encrypt(&self, data: &[u8], context: &SecurityContext) -> crate::core::error::Result<Vec<u8>> {
let key = self.derive_data_key(context)?;
let encrypted = self.encrypt_aes_gcm(data, &key)?;
serde_json::to_vec(&encrypted)
.map_err(|e| crate::core::error::RustChainError::Security(format!("Failed to serialize encrypted data: {}", e)))
}
async fn decrypt(&self, encrypted_data: &[u8], context: &SecurityContext) -> crate::core::error::Result<Vec<u8>> {
let encrypted: EncryptedData = serde_json::from_slice(encrypted_data)
.map_err(|e| crate::core::error::RustChainError::Security(format!("Failed to deserialize encrypted data: {}", e)))?;
let key = self.derive_data_key(context)?;
self.decrypt_aes_gcm(&encrypted, &key)
}
async fn encrypt_with_key(&self, data: &[u8], key: &[u8]) -> crate::core::error::Result<EncryptedData> {
self.encrypt_aes_gcm(data, key)
}
async fn decrypt_with_key(&self, encrypted: &EncryptedData, key: &[u8]) -> crate::core::error::Result<Vec<u8>> {
self.decrypt_aes_gcm(encrypted, key)
}
async fn derive_key(&self, password: &str, params: &KeyDerivationParams) -> crate::core::error::Result<Vec<u8>> {
use sha2::{Sha256, Digest};
let mut key = password.as_bytes().to_vec();
for _ in 0..params.iterations {
let mut hasher = Sha256::new();
hasher.update(&key);
hasher.update(¶ms.salt);
key = hasher.finalize().to_vec();
}
Ok(key[..params.key_length.min(32)].to_vec())
}
async fn generate_key(&self, algorithm: &EncryptionAlgorithm) -> crate::core::error::Result<Vec<u8>> {
use sha2::{Sha256, Digest};
let key_size = match algorithm {
EncryptionAlgorithm::Aes256Gcm => 32,
EncryptionAlgorithm::ChaCha20Poly1305 => 32,
EncryptionAlgorithm::Aes256Cbc => 32,
};
let mut hasher = Sha256::new();
hasher.update(uuid::Uuid::new_v4().as_bytes());
hasher.update(chrono::Utc::now().timestamp().to_be_bytes());
let hash = hasher.finalize();
Ok(hash[..key_size].to_vec())
}
}
pub struct FieldEncryptionService {
base_service: Box<dyn EncryptionService>,
}
impl FieldEncryptionService {
pub fn new(base_service: Box<dyn EncryptionService>) -> Self {
Self { base_service }
}
pub async fn encrypt_field(&self, field_name: &str, value: &str, context: &SecurityContext) -> crate::core::error::Result<String> {
let data = format!("{}:{}", field_name, value);
let encrypted = self.base_service.encrypt(data.as_bytes(), context).await?;
Ok(base64::encode(encrypted))
}
pub async fn decrypt_field(&self, field_name: &str, encrypted_value: &str, context: &SecurityContext) -> crate::core::error::Result<String> {
let encrypted_data = base64::decode(encrypted_value)
.map_err(|e| crate::core::error::RustChainError::Security(format!("Invalid base64: {}", e)))?;
let decrypted = self.base_service.decrypt(&encrypted_data, context).await?;
let data = String::from_utf8(decrypted)
.map_err(|e| crate::core::error::RustChainError::Security(format!("Invalid UTF-8: {}", e)))?;
let prefix = format!("{}:", field_name);
if data.starts_with(&prefix) {
Ok(data[prefix.len()..].to_string())
} else {
Err(crate::core::error::RustChainError::Security("Field name mismatch".to_string()))
}
}
}
pub struct KeyManagementService {
keys: std::collections::HashMap<String, Vec<u8>>,
encryption_service: Box<dyn EncryptionService>,
}
impl KeyManagementService {
pub fn new(encryption_service: Box<dyn EncryptionService>) -> Self {
Self {
keys: std::collections::HashMap::new(),
encryption_service,
}
}
pub async fn generate_data_encryption_key(&mut self, key_id: &str, algorithm: &EncryptionAlgorithm) -> crate::core::error::Result<String> {
let key = self.encryption_service.generate_key(algorithm).await?;
self.keys.insert(key_id.to_string(), key);
Ok(key_id.to_string())
}
pub async fn encrypt_with_key(&self, key_id: &str, data: &[u8]) -> crate::core::error::Result<Vec<u8>> {
let key = self.keys.get(key_id)
.ok_or_else(|| crate::core::error::RustChainError::Security("Key not found".to_string()))?;
let encrypted = self.encryption_service.encrypt_with_key(data, key).await?;
serde_json::to_vec(&encrypted)
.map_err(|e| crate::core::error::RustChainError::Security(format!("Failed to serialize: {}", e)))
}
pub async fn decrypt_with_key(&self, key_id: &str, encrypted_data: &[u8]) -> crate::core::error::Result<Vec<u8>> {
let key = self.keys.get(key_id)
.ok_or_else(|| crate::core::error::RustChainError::Security("Key not found".to_string()))?;
let encrypted: EncryptedData = serde_json::from_slice(encrypted_data)
.map_err(|e| crate::core::error::RustChainError::Security(format!("Failed to deserialize: {}", e)))?;
self.encryption_service.decrypt_with_key(&encrypted, key).await
}
pub fn list_keys(&self) -> Vec<String> {
self.keys.keys().cloned().collect()
}
pub fn delete_key(&mut self, key_id: &str) -> crate::core::error::Result<()> {
self.keys.remove(key_id);
Ok(())
}
}
mod base64 {
pub fn encode(data: Vec<u8>) -> String {
hex::encode(data) }
pub fn decode(data: &str) -> Result<Vec<u8>, hex::FromHexError> {
hex::decode(data)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::security::{SecurityContext, SecurityLevel};
use uuid::Uuid;
#[tokio::test]
async fn test_aes_encryption() {
let encryption_service = AesEncryptionService::new().unwrap();
let context = SecurityContext {
session_id: Uuid::new_v4(),
user_id: Some("test_user".to_string()),
tenant_id: Some("test_tenant".to_string()),
permissions: vec![],
security_level: SecurityLevel::Internal,
created_at: chrono::Utc::now(),
expires_at: None,
};
let plaintext = b"Hello, World! This is a secret message.";
let encrypted = encryption_service.encrypt(plaintext, &context).await.unwrap();
let decrypted = encryption_service.decrypt(&encrypted, &context).await.unwrap();
assert_eq!(plaintext, decrypted.as_slice());
}
#[tokio::test]
async fn test_key_derivation() {
let encryption_service = AesEncryptionService::new().unwrap();
let params = KeyDerivationParams {
salt: b"test_salt".to_vec(),
iterations: 1000,
key_length: 32,
};
let key1 = encryption_service.derive_key("password123", ¶ms).await.unwrap();
let key2 = encryption_service.derive_key("password123", ¶ms).await.unwrap();
assert_eq!(key1, key2);
assert_eq!(key1.len(), 32);
}
#[tokio::test]
async fn test_field_encryption() {
let base_service = Box::new(AesEncryptionService::new().unwrap());
let field_service = FieldEncryptionService::new(base_service);
let context = SecurityContext {
session_id: Uuid::new_v4(),
user_id: Some("test_user".to_string()),
tenant_id: Some("test_tenant".to_string()),
permissions: vec![],
security_level: SecurityLevel::Confidential,
created_at: chrono::Utc::now(),
expires_at: None,
};
let field_name = "ssn";
let value = "123-45-6789";
let encrypted = field_service.encrypt_field(field_name, value, &context).await.unwrap();
let decrypted = field_service.decrypt_field(field_name, &encrypted, &context).await.unwrap();
assert_eq!(value, decrypted);
}
}