use anyhow::{Result, anyhow};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex, RwLock};
use tracing::{error, info, warn};
use std::time::Duration;
use std::time::SystemTime;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EncryptionAlgorithm {
AES256GCM,
ChaCha20Poly1305,
RSA4096,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum KeyType {
Symmetric,
Asymmetric,
HMAC,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum KeyState {
Active,
Expired,
Revoked,
Suspended,
}
#[derive(Debug, Clone)]
pub struct CryptographicKey {
pub id: String,
pub key_type: KeyType,
pub algorithm: EncryptionAlgorithm,
pub key_data: Vec<u8>,
pub created_at: std::time::SystemTime,
pub expires_at: Option<std::time::SystemTime>,
pub state: KeyState,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptionConfig {
pub default_algorithm: EncryptionAlgorithm,
pub key_rotation_interval_days: u32,
pub enable_hsm: bool,
pub backup_keys: bool,
}
#[derive(Debug)]
pub struct KeyManagementService {
keys: Arc<RwLock<HashMap<String, CryptographicKey>>>,
config: EncryptionConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptionResult {
pub success: bool,
pub encrypted_data: Option<Vec<u8>>,
pub key_id: String,
pub iv: Option<Vec<u8>>,
pub tag: Option<Vec<u8>>,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DecryptionResult {
pub success: bool,
pub decrypted_data: Option<Vec<u8>>,
pub key_id: String,
pub error: Option<String>,
}
impl KeyManagementService {
pub fn new(config: EncryptionConfig) -> Self {
info!("Initializing Key Management Service");
Self {
keys: Arc::new(Mutex::new(HashMap::new()))
config,
}
}
pub async fn generate_key(
&self,
key_type: KeyType,
algorithm: EncryptionAlgorithm,
) -> Result<CryptographicKey> {
let key_id: _ = format!("key_{}", uuid::Uuid::new_v4());
let key_data: _ = match (key_type.clone(), algorithm.clone()) {
(KeyType::Symmetric, EncryptionAlgorithm::AES256GCM) => {
vec![0u8; 32]
}
(KeyType::Symmetric, EncryptionAlgorithm::ChaCha20Poly1305) => {
vec![0u8; 32]
}
(KeyType::Asymmetric, EncryptionAlgorithm::RSA4096) => {
vec![0u8; 512]
}
(KeyType::HMAC, _) => {
vec![0u8; 32]
}
_ => return Err(anyhow!("Unsupported key type or algorithm")),
};
let key: _ = CryptographicKey {
id: key_id.clone(),
key_type,
algorithm,
key_data,
created_at: std::time::SystemTime::now(),
expires_at: Some(
std::time::SystemTime::now()
+ std::time::Duration::from_secs(365 * 24 * 60 * 60)
),
state: KeyState::Active,
metadata: HashMap::new(),
};
let mut keys = self.keys.write().await;
keys.insert(key_id, key.clone());
info!("Generated new key: {} ({:?})", key_id, key.algorithm);
Ok(key)
}
pub async fn encrypt(
&self,
key_id: &str,
plaintext: &[u8],
) -> Result<EncryptionResult> {
let keys: _ = self.keys.read().await;
if let Some(key) = keys.get(key_id) {
if key.state != KeyState::Active {
return Ok(EncryptionResult {
success: false,
encrypted_data: None,
key_id: key_id.to_string(),
iv: None,
tag: None,
error: Some("Key is not active".to_string()),
});
}
match key.algorithm {
EncryptionAlgorithm::AES256GCM => {
let iv: _ = vec![0u8; 12]; let tag: _ = vec![0u8; 16]; let encrypted: _ = plaintext.to_vec();
info!("Encrypted data using key: {} (AES-256-GCM)", key_id);
Ok(EncryptionResult {
success: true,
encrypted_data: Some(encrypted),
key_id: key_id.to_string(),
iv: Some(iv),
tag: Some(tag),
error: None,
})
}
_ => Ok(EncryptionResult {
success: false,
encrypted_data: None,
key_id: key_id.to_string(),
iv: None,
tag: None,
error: Some(format!("Unsupported algorithm: {:?}", key.algorithm)),
}),
}
} else {
Ok(EncryptionResult {
success: false,
encrypted_data: None,
key_id: key_id.to_string(),
iv: None,
tag: None,
error: Some("Key not found".to_string()),
})
}
}
pub async fn decrypt(
&self,
key_id: &str,
encrypted_data: &[u8],
iv: &[u8],
tag: &[u8],
) -> Result<DecryptionResult> {
let keys: _ = self.keys.read().await;
if let Some(key) = keys.get(key_id) {
if key.state != KeyState::Active {
return Ok(DecryptionResult {
success: false,
decrypted_data: None,
key_id: key_id.to_string(),
error: Some("Key is not active".to_string()),
});
}
match key.algorithm {
EncryptionAlgorithm::AES256GCM => {
let decrypted: _ = encrypted_data.to_vec();
info!("Decrypted data using key: {} (AES-256-GCM)", key_id);
Ok(DecryptionResult {
success: true,
decrypted_data: Some(decrypted),
key_id: key_id.to_string(),
error: None,
})
}
_ => Ok(DecryptionResult {
success: false,
decrypted_data: None,
key_id: key_id.to_string(),
error: Some(format!("Unsupported algorithm: {:?}", key.algorithm)),
}),
}
} else {
Ok(DecryptionResult {
success: false,
decrypted_data: None,
key_id: key_id.to_string(),
error: Some("Key not found".to_string()),
})
}
}
pub async fn rotate_key(&self, key_id: &str) -> Result<CryptographicKey> {
let mut keys = self.keys.write().await;
if let Some(old_key) = keys.get_mut(key_id) {
old_key.state = KeyState::Expired;
let new_key: _ = self.generate_key(old_key.key_type.clone(), old_key.algorithm.clone()).await?;
info!("Rotated key: {} -> {}", key_id, new_key.id);
Ok(new_key)
} else {
Err(anyhow!("Key not found: {}", key_id))
}
}
pub async fn revoke_key(&self, key_id: &str, reason: &str) -> Result<()> {
let mut keys = self.keys.write().await;
if let Some(key) = keys.get_mut(key_id) {
key.state = KeyState::Revoked;
key.metadata.insert("revocation_reason".to_string(), reason.to_string());
key.metadata.insert("revoked_at".to_string(), format!("{:?}", std::time::SystemTime::now());
warn!("Revoked key: {} (reason: {})", key_id, reason);
Ok(())
} else {
Err(anyhow!("Key not found: {}", key_id))
}
}
pub async fn get_key(&self, key_id: &str) -> Option<CryptographicKey> {
let keys: _ = self.keys.read().await;
keys.get(key_id).cloned()
}
pub async fn list_keys(&self) -> Vec<CryptographicKey> {
let keys: _ = self.keys.read().await;
keys.values().cloned().collect()
}
pub async fn get_key_stats(&self) -> HashMap<String, serde_json::Value> {
let keys: _ = self.keys.read().await;
let mut stats = HashMap::new();
stats.insert("total_keys".to_string(), serde_json::Value::from(keys.len());
let mut state_counts = HashMap::new();
for key in keys.values() {
let state_name: _ = match key.state {
KeyState::Active => "Active",
KeyState::Expired => "Expired",
KeyState::Revoked => "Revoked",
KeyState::Suspended => "Suspended",
};
*state_counts.entry(state_name).or_insert(0) += 1;
}
stats.insert("key_states".to_string(), serde_json::to_value(state_counts).unwrap());
let mut algo_counts = HashMap::new();
for key in keys.values() {
let algo_name: _ = match &key.algorithm {
EncryptionAlgorithm::AES256GCM => "AES-256-GCM",
EncryptionAlgorithm::ChaCha20Poly1305 => "ChaCha20-Poly1305",
EncryptionAlgorithm::RSA4096 => "RSA-4096",
EncryptionAlgorithm::Custom(name) => name.as_str(),
};
*algo_counts.entry(algo_name).or_insert(0) += 1;
}
stats.insert("algorithms".to_string(), serde_json::to_value(algo_counts).unwrap());
stats
}
pub async fn cleanup_expired_keys(&self) -> Result<usize> {
let mut keys = self.keys.write().await;
let now: _ = std::time::SystemTime::now();
let mut removed_count = 0;
keys.retain(|_, key| {
if let Some(expires_at) = key.expires_at {
if expires_at < now && key.state == KeyState::Expired {
removed_count += 1;
false } else {
true
}
} else {
true }
});
info!("Cleaned up {} expired keys", removed_count);
Ok(removed_count)
}
}
#[cfg(test)]
mod tests {
#[tokio::test]
async fn test_key_generation() {
let config: _ = EncryptionConfig {
default_algorithm: EncryptionAlgorithm::AES256GCM,
key_rotation_interval_days: 90,
enable_hsm: false,
backup_keys: true,
};
let kms: _ = KeyManagementService::new(config);
let key: _ = kms.generate_key(
KeyType::Symmetric,
EncryptionAlgorithm::AES256GCM,
).await.unwrap();
assert_eq!(key.key_type, KeyType::Symmetric);
assert_eq!(key.algorithm, EncryptionAlgorithm::AES256GCM);
assert_eq!(key.state, KeyState::Active);
}
#[tokio::test]
async fn test_encryption_decryption() {
let config: _ = EncryptionConfig {
default_algorithm: EncryptionAlgorithm::AES256GCM,
key_rotation_interval_days: 90,
enable_hsm: false,
backup_keys: true,
};
let kms: _ = KeyManagementService::new(config);
let key: _ = kms.generate_key(
KeyType::Symmetric,
EncryptionAlgorithm::AES256GCM,
).await.unwrap();
let plaintext: _ = b"Hello, Amber!";
let encrypted: _ = kms.encrypt(&key.id, plaintext).await.unwrap();
assert!(encrypted.success);
let decrypted: _ = kms.decrypt(
&key.id,
encrypted.encrypted_data.as_ref().unwrap(),
encrypted.iv.as_ref().unwrap(),
encrypted.tag.as_ref().unwrap(),
).await.unwrap();
assert!(decrypted.success);
assert_eq!(decrypted.decrypted_data.as_ref().unwrap(), plaintext);
}
#[tokio::test]
async fn test_key_rotation() {
let config: _ = EncryptionConfig {
default_algorithm: EncryptionAlgorithm::AES256GCM,
key_rotation_interval_days: 90,
enable_hsm: false,
backup_keys: true,
};
let kms: _ = KeyManagementService::new(config);
let original_key: _ = kms.generate_key(
KeyType::Symmetric,
EncryptionAlgorithm::AES256GCM,
).await.unwrap();
let new_key: _ = kms.rotate_key(&original_key.id).await.unwrap();
assert_ne!(original_key.id, new_key.id);
assert_eq!(new_key.key_type, original_key.key_type);
assert_eq!(new_key.algorithm, original_key.algorithm);
}
#[tokio::test]
async fn test_key_revoke() {
let config: _ = EncryptionConfig {
default_algorithm: EncryptionAlgorithm::AES256GCM,
key_rotation_interval_days: 90,
enable_hsm: false,
backup_keys: true,
};
let kms: _ = KeyManagementService::new(config);
let key: _ = kms.generate_key(
KeyType::Symmetric,
EncryptionAlgorithm::AES256GCM,
).await.unwrap();
kms.revoke_key(&key.id, "Security incident").await.unwrap();
let retrieved_key: _ = kms.get_key(&key.id).await.unwrap();
assert_eq!(retrieved_key.state, KeyState::Revoked);
}
}