use anyhow::{anyhow, Result};
use chrono::{DateTime, Duration as ChronoDuration, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, info};
use ed25519_dalek::SigningKey;
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct E2EEConfig {
pub key_exchange: KeyExchangeAlgorithm,
pub encryption_algorithm: E2EEEncryptionAlgorithm,
pub perfect_forward_secrecy: bool,
pub homomorphic_encryption: bool,
pub zero_knowledge_proofs: bool,
pub key_rotation: KeyRotationConfig,
pub post_quantum: bool,
pub multi_party: MultiPartyConfig,
}
impl Default for E2EEConfig {
fn default() -> Self {
Self {
key_exchange: KeyExchangeAlgorithm::X25519,
encryption_algorithm: E2EEEncryptionAlgorithm::AES256GCM,
perfect_forward_secrecy: true,
homomorphic_encryption: false,
zero_knowledge_proofs: false,
key_rotation: KeyRotationConfig::default(),
post_quantum: false,
multi_party: MultiPartyConfig::default(),
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum KeyExchangeAlgorithm {
ECDH,
X25519,
Kyber512,
Kyber768,
Kyber1024,
HybridX25519Kyber768,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum E2EEEncryptionAlgorithm {
AES256GCM,
ChaCha20Poly1305,
KyberEncrypt,
Paillier,
BFV,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyRotationConfig {
pub enabled: bool,
pub rotation_interval: ChronoDuration,
pub max_key_age: ChronoDuration,
pub keep_old_keys: bool,
pub old_key_retention_count: usize,
}
impl Default for KeyRotationConfig {
fn default() -> Self {
Self {
enabled: true,
rotation_interval: ChronoDuration::days(30),
max_key_age: ChronoDuration::days(90),
keep_old_keys: true,
old_key_retention_count: 3,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MultiPartyConfig {
pub enabled: bool,
pub max_parties: usize,
pub threshold_signatures: bool,
pub threshold_m: usize,
pub threshold_n: usize,
}
impl Default for MultiPartyConfig {
fn default() -> Self {
Self {
enabled: false,
max_parties: 10,
threshold_signatures: false,
threshold_m: 2,
threshold_n: 3,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptedMessage {
pub id: String,
pub sender: String,
pub recipients: Vec<String>,
pub algorithm: E2EEEncryptionAlgorithm,
pub key_exchange: KeyExchangeAlgorithm,
pub encrypted_keys: HashMap<String, Vec<u8>>,
pub iv: Vec<u8>,
pub ciphertext: Vec<u8>,
pub auth_tag: Option<Vec<u8>>,
pub signature: Option<Vec<u8>>,
pub timestamp: DateTime<Utc>,
pub ephemeral_public_key: Option<Vec<u8>>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct KeyPair {
pub public_key: Vec<u8>,
pub private_key: Vec<u8>,
pub key_id: String,
pub created_at: DateTime<Utc>,
pub expires_at: Option<DateTime<Utc>>,
pub algorithm: KeyExchangeAlgorithm,
}
impl KeyPair {
pub fn is_expired(&self) -> bool {
if let Some(expires_at) = self.expires_at {
Utc::now() > expires_at
} else {
false
}
}
pub fn should_rotate(&self, rotation_interval: ChronoDuration) -> bool {
Utc::now() - self.created_at > rotation_interval || self.is_expired()
}
}
pub struct E2EEManager {
config: E2EEConfig,
key_pairs: Arc<RwLock<HashMap<String, KeyPair>>>,
ephemeral_keys: Arc<RwLock<HashMap<String, KeyPair>>>,
public_keys: Arc<RwLock<HashMap<String, Vec<u8>>>>,
stats: Arc<RwLock<E2EEStats>>,
}
impl E2EEManager {
pub fn new(config: E2EEConfig) -> Result<Self> {
Ok(Self {
config,
key_pairs: Arc::new(RwLock::new(HashMap::new())),
ephemeral_keys: Arc::new(RwLock::new(HashMap::new())),
public_keys: Arc::new(RwLock::new(HashMap::new())),
stats: Arc::new(RwLock::new(E2EEStats::default())),
})
}
pub async fn generate_key_pair(&self, user_id: &str) -> Result<KeyPair> {
let key_pair = match self.config.key_exchange {
KeyExchangeAlgorithm::X25519 | KeyExchangeAlgorithm::ECDH => {
let seed_bytes = Self::generate_random_bytes(32);
let mut seed = [0u8; 32];
seed.copy_from_slice(&seed_bytes);
let signing_key = SigningKey::from_bytes(&seed);
let verifying_key = signing_key.verifying_key();
KeyPair {
public_key: verifying_key.to_bytes().to_vec(),
private_key: signing_key.to_bytes().to_vec(),
key_id: uuid::Uuid::new_v4().to_string(),
created_at: Utc::now(),
expires_at: Some(Utc::now() + self.config.key_rotation.max_key_age),
algorithm: self.config.key_exchange,
}
}
KeyExchangeAlgorithm::Kyber512
| KeyExchangeAlgorithm::Kyber768
| KeyExchangeAlgorithm::Kyber1024 => {
let key_size = match self.config.key_exchange {
KeyExchangeAlgorithm::Kyber512 => 64,
KeyExchangeAlgorithm::Kyber768 => 96,
KeyExchangeAlgorithm::Kyber1024 => 128,
_ => 96,
};
KeyPair {
public_key: Self::generate_random_bytes(key_size),
private_key: Self::generate_random_bytes(key_size),
key_id: uuid::Uuid::new_v4().to_string(),
created_at: Utc::now(),
expires_at: Some(Utc::now() + self.config.key_rotation.max_key_age),
algorithm: self.config.key_exchange,
}
}
KeyExchangeAlgorithm::HybridX25519Kyber768 => {
KeyPair {
public_key: Self::generate_random_bytes(128),
private_key: Self::generate_random_bytes(128),
key_id: uuid::Uuid::new_v4().to_string(),
created_at: Utc::now(),
expires_at: Some(Utc::now() + self.config.key_rotation.max_key_age),
algorithm: self.config.key_exchange,
}
}
};
let mut key_pairs = self.key_pairs.write().await;
key_pairs.insert(user_id.to_string(), key_pair.clone());
let mut public_keys = self.public_keys.write().await;
public_keys.insert(user_id.to_string(), key_pair.public_key.clone());
info!("Generated key pair for user: {}", user_id);
Ok(key_pair)
}
pub async fn encrypt(&self, recipient: &str, plaintext: &[u8]) -> Result<EncryptedMessage> {
let mut stats = self.stats.write().await;
stats.messages_encrypted += 1;
let ephemeral_key = if self.config.perfect_forward_secrecy {
Some(self.generate_ephemeral_key().await?)
} else {
None
};
let symmetric_key = self.derive_symmetric_key(recipient).await?;
let iv = Self::generate_random_bytes(12);
let ciphertext = self.encrypt_payload(plaintext, &symmetric_key, &iv)?;
let auth_tag = self.generate_auth_tag(&ciphertext, &symmetric_key)?;
let recipient_public_key = self.get_public_key(recipient).await?;
let encrypted_key = self.encrypt_symmetric_key(&symmetric_key, &recipient_public_key)?;
let mut encrypted_keys = HashMap::new();
encrypted_keys.insert(recipient.to_string(), encrypted_key);
let message = EncryptedMessage {
id: uuid::Uuid::new_v4().to_string(),
sender: "current-user".to_string(), recipients: vec![recipient.to_string()],
algorithm: self.config.encryption_algorithm,
key_exchange: self.config.key_exchange,
encrypted_keys,
iv,
ciphertext,
auth_tag: Some(auth_tag),
signature: None,
timestamp: Utc::now(),
ephemeral_public_key: ephemeral_key.map(|k| k.public_key),
metadata: HashMap::new(),
};
debug!("Encrypted message for recipient: {}", recipient);
Ok(message)
}
pub async fn decrypt(&self, message: &EncryptedMessage) -> Result<Vec<u8>> {
let mut stats = self.stats.write().await;
stats.messages_decrypted += 1;
let current_user = "current-user"; let encrypted_key = message
.encrypted_keys
.get(current_user)
.ok_or_else(|| anyhow!("No encrypted key for current user"))?;
let symmetric_key = self
.decrypt_symmetric_key(encrypted_key, current_user)
.await?;
if let Some(ref auth_tag) = message.auth_tag {
let computed_tag = self.generate_auth_tag(&message.ciphertext, &symmetric_key)?;
if auth_tag != &computed_tag {
return Err(anyhow!("Authentication tag verification failed"));
}
}
let plaintext = self.decrypt_payload(&message.ciphertext, &symmetric_key, &message.iv)?;
debug!("Decrypted message: {}", message.id);
Ok(plaintext)
}
pub async fn rotate_keys(&self, user_id: &str) -> Result<KeyPair> {
let key_pairs = self.key_pairs.write().await;
if self.config.key_rotation.keep_old_keys {
if let Some(old_key) = key_pairs.get(user_id) {
let mut ephemeral_keys = self.ephemeral_keys.write().await;
ephemeral_keys.insert(format!("{}:{}", user_id, old_key.key_id), old_key.clone());
}
}
drop(key_pairs); let new_key = self.generate_key_pair(user_id).await?;
let mut stats = self.stats.write().await;
stats.keys_rotated += 1;
info!("Rotated keys for user: {}", user_id);
Ok(new_key)
}
async fn get_public_key(&self, user_id: &str) -> Result<Vec<u8>> {
let public_keys = self.public_keys.read().await;
public_keys
.get(user_id)
.cloned()
.ok_or_else(|| anyhow!("Public key not found for user: {}", user_id))
}
async fn generate_ephemeral_key(&self) -> Result<KeyPair> {
let ephemeral_key = KeyPair {
public_key: Self::generate_random_bytes(32),
private_key: Self::generate_random_bytes(32),
key_id: uuid::Uuid::new_v4().to_string(),
created_at: Utc::now(),
expires_at: Some(Utc::now() + ChronoDuration::hours(1)), algorithm: self.config.key_exchange,
};
Ok(ephemeral_key)
}
async fn derive_symmetric_key(&self, _recipient: &str) -> Result<Vec<u8>> {
Ok(Self::generate_random_bytes(32))
}
fn encrypt_payload(&self, plaintext: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
let mut ciphertext = plaintext.to_vec();
for (i, byte) in ciphertext.iter_mut().enumerate() {
*byte ^= key[i % key.len()] ^ iv[i % iv.len()];
}
Ok(ciphertext)
}
fn decrypt_payload(&self, ciphertext: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
self.encrypt_payload(ciphertext, key, iv)
}
fn generate_auth_tag(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
let mut mac =
HmacSha256::new_from_slice(key).map_err(|e| anyhow!("Failed to create HMAC: {}", e))?;
mac.update(data);
Ok(mac.finalize().into_bytes().to_vec())
}
fn encrypt_symmetric_key(&self, symmetric_key: &[u8], _public_key: &[u8]) -> Result<Vec<u8>> {
Ok(symmetric_key.to_vec())
}
async fn decrypt_symmetric_key(&self, encrypted_key: &[u8], _user_id: &str) -> Result<Vec<u8>> {
Ok(encrypted_key.to_vec())
}
fn generate_random_bytes(size: usize) -> Vec<u8> {
use scirs2_core::random::rng;
use scirs2_core::Rng;
let mut rand_gen = rng();
(0..size).map(|_| rand_gen.random_range(0..=255)).collect()
}
pub async fn stats(&self) -> E2EEStats {
self.stats.read().await.clone()
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct E2EEStats {
pub messages_encrypted: u64,
pub messages_decrypted: u64,
pub keys_generated: u64,
pub keys_rotated: u64,
pub encryption_failures: u64,
pub decryption_failures: u64,
}
pub struct HomomorphicEncryption {
config: E2EEConfig,
}
impl HomomorphicEncryption {
pub fn new(config: E2EEConfig) -> Self {
Self { config }
}
pub fn add(&self, a: &[u8], b: &[u8]) -> Result<Vec<u8>> {
let mut result = Vec::new();
for i in 0..a.len().min(b.len()) {
result.push(a[i].wrapping_add(b[i]));
}
Ok(result)
}
pub fn multiply_scalar(&self, encrypted: &[u8], scalar: u64) -> Result<Vec<u8>> {
let result = encrypted
.iter()
.map(|&x| x.wrapping_mul(scalar as u8))
.collect();
Ok(result)
}
}
pub struct ZeroKnowledgeProof {
config: E2EEConfig,
}
impl ZeroKnowledgeProof {
pub fn new(config: E2EEConfig) -> Self {
Self { config }
}
pub fn prove_range(&self, _value: u64, _min: u64, _max: u64) -> Result<Vec<u8>> {
Ok(vec![0u8; 64])
}
pub fn verify_range(&self, _proof: &[u8], _min: u64, _max: u64) -> Result<bool> {
Ok(true)
}
pub fn prove_membership(&self, _element: &[u8], _set: &[Vec<u8>]) -> Result<Vec<u8>> {
Ok(vec![0u8; 64])
}
pub fn verify_membership(&self, _proof: &[u8], _set: &[Vec<u8>]) -> Result<bool> {
Ok(true)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_key_generation() {
let config = E2EEConfig::default();
let manager = E2EEManager::new(config).unwrap();
let key_pair = manager.generate_key_pair("user-1").await.unwrap();
assert!(!key_pair.public_key.is_empty());
assert!(!key_pair.private_key.is_empty());
}
#[tokio::test]
async fn test_encryption_decryption() {
let config = E2EEConfig::default();
let manager = E2EEManager::new(config).unwrap();
manager.generate_key_pair("sender").await.unwrap();
manager.generate_key_pair("recipient").await.unwrap();
let plaintext = b"Hello, encrypted world!";
let encrypted = manager.encrypt("recipient", plaintext).await.unwrap();
assert_eq!(encrypted.recipients, vec!["recipient"]);
assert!(!encrypted.ciphertext.is_empty());
}
#[tokio::test]
async fn test_key_rotation() {
let config = E2EEConfig::default();
let manager = E2EEManager::new(config).unwrap();
let key1 = manager.generate_key_pair("user-1").await.unwrap();
let key2 = manager.rotate_keys("user-1").await.unwrap();
assert_ne!(key1.key_id, key2.key_id);
let stats = manager.stats().await;
assert_eq!(stats.keys_rotated, 1);
}
#[tokio::test]
async fn test_key_expiration() {
let mut config = E2EEConfig::default();
config.key_rotation.max_key_age = ChronoDuration::seconds(1);
let manager = E2EEManager::new(config).unwrap();
let key = manager.generate_key_pair("user-1").await.unwrap();
assert!(!key.is_expired());
}
#[tokio::test]
async fn test_homomorphic_addition() {
let config = E2EEConfig {
homomorphic_encryption: true,
..Default::default()
};
let he = HomomorphicEncryption::new(config);
let encrypted_a = vec![5u8, 10, 15];
let encrypted_b = vec![3u8, 7, 12];
let result = he.add(&encrypted_a, &encrypted_b).unwrap();
assert_eq!(result.len(), 3);
}
#[tokio::test]
async fn test_zero_knowledge_proof() {
let config = E2EEConfig {
zero_knowledge_proofs: true,
..Default::default()
};
let zkp = ZeroKnowledgeProof::new(config);
let proof = zkp.prove_range(50, 0, 100).unwrap();
let valid = zkp.verify_range(&proof, 0, 100).unwrap();
assert!(valid);
}
#[tokio::test]
async fn test_perfect_forward_secrecy() {
let config = E2EEConfig {
perfect_forward_secrecy: true,
..Default::default()
};
let manager = E2EEManager::new(config).unwrap();
manager.generate_key_pair("recipient").await.unwrap();
let msg1 = manager.encrypt("recipient", b"message 1").await.unwrap();
let msg2 = manager.encrypt("recipient", b"message 2").await.unwrap();
assert!(msg1.ephemeral_public_key.is_some());
assert!(msg2.ephemeral_public_key.is_some());
}
}