// rust/01-input-validation.rs/*Input validation patterns and best practices*/usestd::collections::HashMap;usestd::sync::Arc;usestd::time::{Duration,Instant};usetokio::sync::RwLock;useserde::{Deserialize,Serialize};useregex::Regex;/// Input validator.pubstructInputValidator{patterns:HashMap<String,Regex>,max_lengths:HashMap<String,usize>,allowed_chars:HashMap<String,Regex>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructValidationResult{pubis_valid:bool,puberrors:Vec<String>,pubsanitized_value:Option<String>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructValidationRule{pubfield_name:String,pubrequired:bool,pubmin_length:Option<usize>,pubmax_length:Option<usize>,pubpattern:Option<String>,puballowed_values:Option<Vec<String>>,pubcustom_validator:Option<String>,}implInputValidator{pubfnnew()->Self{letmutpatterns=HashMap::new();letmutmax_lengths=HashMap::new();letmutallowed_chars=HashMap::new();// Email patternpatterns.insert("email".to_string(),Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap());// Phone patternpatterns.insert("phone".to_string(),Regex::new(r"^\+?[1-9]\d{1,14}$").unwrap());// URL patternpatterns.insert("url".to_string(),Regex::new(r"^https?://[^\s/$.?#].[^\s]*$").unwrap());// Alphanumeric patternpatterns.insert("alphanumeric".to_string(),Regex::new(r"^[a-zA-Z0-9]+$").unwrap());// Set max lengthsmax_lengths.insert("email".to_string(),254);max_lengths.insert("phone".to_string(),15);max_lengths.insert("url".to_string(),2048);max_lengths.insert("name".to_string(),100);max_lengths.insert("description".to_string(),1000);// Set allowed charactersallowed_chars.insert("name".to_string(),Regex::new(r"^[a-zA-Z\s\-'\.]+$").unwrap());allowed_chars.insert("description".to_string(),Regex::new(r"^[a-zA-Z0-9\s\-'\.\,\!\?]+$").unwrap());Self{patterns,max_lengths,allowed_chars,}}/// Validate a single field.pubfnvalidate_field(&self,field_name:&str,value:&str,rules:&ValidationRule)->ValidationResult{letmuterrors=Vec::new();letmutsanitized_value=Some(value.to_string());// Check if requiredifrules.required&&value.trim().is_empty(){errors.push(format!("Field '{}' is required",field_name));returnValidationResult{is_valid:false,errors,sanitized_value:None,};}// Skip validation for empty optional fieldsif!rules.required&&value.trim().is_empty(){returnValidationResult{is_valid:true,errors:Vec::new(),sanitized_value:Some(String::new()),};}lettrimmed_value=value.trim();// Check minimum lengthifletSome(min_length)=rules.min_length{iftrimmed_value.len()<min_length{errors.push(format!("Field '{}' must be at least {} characters long",field_name,min_length));}}// Check maximum lengthifletSome(max_length)=rules.max_length{iftrimmed_value.len()>max_length{errors.push(format!("Field '{}' must be no more than {} characters long",field_name,max_length));}}// Check patternifletSome(pattern)=&rules.pattern{ifletOk(regex)=Regex::new(pattern){if!regex.is_match(trimmed_value){errors.push(format!("Field '{}' does not match required pattern",field_name));}}}// Check allowed valuesifletSome(allowed_values)=&rules.allowed_values{if!allowed_values.contains(&trimmed_value.to_string()){errors.push(format!("Field '{}' must be one of: {}",field_name,allowed_values.join(", ")));}}// Check against predefined patternsifletSome(pattern_name)=self.get_pattern_name(field_name){ifletSome(pattern)=self.patterns.get(pattern_name){if!pattern.is_match(trimmed_value){errors.push(format!("Field '{}' does not match required format",field_name));}}}// Check against max lengthsifletSome(max_length)=self.max_lengths.get(field_name){iftrimmed_value.len()>*max_length{errors.push(format!("Field '{}' exceeds maximum length of {}",field_name,max_length));}}// Check allowed charactersifletSome(allowed_chars)=self.allowed_chars.get(field_name){if!allowed_chars.is_match(trimmed_value){errors.push(format!("Field '{}' contains invalid characters",field_name));}}// Sanitize valueiferrors.is_empty(){sanitized_value=Some(self.sanitize_value(trimmed_value));}ValidationResult{is_valid:errors.is_empty(),errors,sanitized_value,}}/// Validate multiple fields.pubfnvalidate_fields(&self,data:&HashMap<String,String>,rules:&[ValidationRule])->HashMap<String,ValidationResult>{letmutresults=HashMap::new();forruleinrules{letvalue=data.get(&rule.field_name).map(|s|s.as_str()).unwrap_or("");letresult=self.validate_field(&rule.field_name,value,rule);results.insert(rule.field_name.clone(),result);}results}/// Get pattern name for field.fnget_pattern_name(&self,field_name:&str)->Option<&str>{matchfield_name{"email"|"email_address"=>Some("email"),"phone"|"phone_number"=>Some("phone"),"url"|"website"=>Some("url"),_=>None,}}/// Sanitize input value.fnsanitize_value(&self,value:&str)->String{// Remove null bytesletsanitized=value.replace('\0',"");// Trim whitespacelettrimmed=sanitized.trim();// Remove control charactersletcleaned=trimmed.chars().filter(|c|!c.is_control()||*c=='\n'||*c=='\r'||*c=='\t').collect::<String>();cleaned}/// Validate JSON input.pubfnvalidate_json(&self,json:&str)->Result<serde_json::Value,String>{// Parse JSONletvalue:serde_json::Value=serde_json::from_str(json).map_err(|e|format!("Invalid JSON: {}",e))?;// Check for dangerous keysifletSome(obj)=value.as_object(){forkeyinobj.keys(){ifkey.starts_with("__")||key.contains("..")||key.contains("$"){returnErr(format!("Dangerous key detected: {}",key));}}}// Check for dangerous valuesifletSome(str_value)=value.as_str(){ifstr_value.contains("<script>")||str_value.contains("javascript:"){returnErr("Dangerous content detected".to_string());}}Ok(value)}/// Validate file upload.pubfnvalidate_file_upload(&self,filename:&str,content_type:&str,size:u64)->Result<(),String>{// Check file extensionletallowed_extensions=["jpg","jpeg","png","gif","pdf","txt","doc","docx"];ifletSome(extension)=filename.split('.').last(){if!allowed_extensions.contains(&extension.to_lowercase().as_str()){returnErr(format!("File type '{}' not allowed",extension));}}// Check content typeletallowed_types=["image/jpeg","image/png","image/gif","application/pdf","text/plain"];if!allowed_types.contains(&content_type){returnErr(format!("Content type '{}' not allowed",content_type));}// Check file size (10MB limit)letmax_size=10*1024*1024;ifsize>max_size{returnErr(format!("File size {} exceeds maximum allowed size {}",size,max_size));}// Check filename for dangerous charactersiffilename.contains("..")||filename.contains("/")||filename.contains("\\"){returnErr("Filename contains dangerous characters".to_string());}Ok(())}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_input_validation(){letvalidator=InputValidator::new();letrules=vec![ValidationRule{field_name:"email".to_string(),required:true,min_length:Some(5),max_length:Some(254),pattern:None,allowed_values:None,custom_validator:None,},ValidationRule{field_name:"name".to_string(),required:true,min_length:Some(2),max_length:Some(100),pattern:None,allowed_values:None,custom_validator:None,},];letmutdata=HashMap::new();data.insert("email".to_string(),"test@example.com".to_string());data.insert("name".to_string(),"John Doe".to_string());letresults=validator.validate_fields(&data,&rules);assert!(results.get("email").unwrap().is_valid);assert!(results.get("name").unwrap().is_valid);}#[test]fntest_json_validation(){letvalidator=InputValidator::new();letvalid_json=r#"{"name": "John", "age": 30}"#;letresult=validator.validate_json(valid_json);assert!(result.is_ok());letdangerous_json=r#"{"__proto__": {"isAdmin": true}}"#;letresult=validator.validate_json(dangerous_json);assert!(result.is_err());}#[test]fntest_file_upload_validation(){letvalidator=InputValidator::new();letresult=validator.validate_file_upload("test.jpg","image/jpeg",1024);assert!(result.is_ok());letresult=validator.validate_file_upload("test.exe","application/octet-stream",1024);assert!(result.is_err());}}
// rust/02-auth-authorization.rs/*Authentication and authorization patterns*/usestd::collections::HashMap;usestd::sync::Arc;usestd::time::{Duration,Instant,SystemTime,UNIX_EPOCH};usetokio::sync::RwLock;useserde::{Deserialize,Serialize};usejsonwebtoken::{decode,encode,Algorithm,DecodingKey,EncodingKey,Header,Validation};useargon2::{Argon2,PasswordHash,PasswordHasher,PasswordVerifier};useargon2::password_hash::{rand_core::OsRng,SaltString};/// Authentication manager.pubstructAuthManager{jwt_secret:String,jwt_expiry:Duration,password_hasher:Argon2<'static>,user_sessions:Arc<RwLock<HashMap<String,UserSession>>>,rate_limiter:Arc<RwLock<HashMap<String,RateLimitInfo>>>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructUser{pubid:String,pubusername:String,pubemail:String,pubpassword_hash:String,pubroles:Vec<String>,pubpermissions:Vec<String>,pubis_active:bool,pubcreated_at:Instant,publast_login:Option<Instant>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructUserSession{pubuser_id:String,pubsession_id:String,pubcreated_at:Instant,pubexpires_at:Instant,pubip_address:String,pubuser_agent:String,pubis_active:bool,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructRateLimitInfo{pubattempts:u32,publast_attempt:Instant,pubblocked_until:Option<Instant>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructLoginRequest{pubusername:String,pubpassword:String,pubip_address:String,pubuser_agent:String,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructLoginResponse{pubtoken:String,pubrefresh_token:String,pubexpires_in:u64,pubuser:User,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructJwtClaims{pubsub:String,// user idpubusername:String,pubroles:Vec<String>,pubpermissions:Vec<String>,pubiat:u64,// issued atpubexp:u64,// expires atpubjti:String,// jwt id}implAuthManager{pubfnnew(jwt_secret:String,jwt_expiry:Duration)->Self{Self{jwt_secret,jwt_expiry,password_hasher:Argon2::default(),user_sessions:Arc::new(RwLock::new(HashMap::new())),rate_limiter:Arc::new(RwLock::new(HashMap::new())),}}/// Register a new user.pubasyncfnregister_user(&self,username:String,email:String,password:String)->Result<User,String>{// Check if user already existsifself.user_exists(&username,&email).await{returnErr("User already exists".to_string());}// Hash passwordletpassword_hash=self.hash_password(&password)?;// Create userletuser=User{id:uuid::Uuid::new_v4().to_string(),username,email,password_hash,roles:vec!["user".to_string()],permissions:vec!["read".to_string()],is_active:true,created_at:Instant::now(),last_login:None,};// Store user (in real implementation, store in database)self.store_user(&user).await?;Ok(user)}/// Authenticate user.pubasyncfnauthenticate(&self,request:LoginRequest)->Result<LoginResponse,String>{// Check rate limitingifself.is_rate_limited(&request.ip_address).await{returnErr("Too many login attempts".to_string());}// Find userletuser=self.find_user_by_username(&request.username).await.ok_or("Invalid credentials")?;// Verify passwordif!self.verify_password(&request.password,&user.password_hash)?{self.record_failed_attempt(&request.ip_address).await;returnErr("Invalid credentials".to_string());}// Check if user is activeif!user.is_active{returnErr("Account is disabled".to_string());}// Generate JWT tokenlettoken=self.generate_jwt_token(&user)?;letrefresh_token=self.generate_refresh_token(&user)?;// Create sessionletsession=UserSession{user_id:user.id.clone(),session_id:uuid::Uuid::new_v4().to_string(),created_at:Instant::now(),expires_at:Instant::now()+self.jwt_expiry,ip_address:request.ip_address,user_agent:request.user_agent,is_active:true,};// Store sessionself.store_session(&session).await?;// Update last loginself.update_last_login(&user.id).await?;// Clear rate limitingself.clear_rate_limit(&request.ip_address).await;Ok(LoginResponse{token,refresh_token,expires_in:self.jwt_expiry.as_secs(),user,})}/// Verify JWT token.pubasyncfnverify_token(&self,token:&str)->Result<JwtClaims,String>{letkey=DecodingKey::from_secret(self.jwt_secret.as_ref());letvalidation=Validation::new(Algorithm::HS256);lettoken_data=decode::<JwtClaims>(token,&key,&validation).map_err(|e|format!("Invalid token: {}",e))?;// Check if token is expiredletnow=SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();iftoken_data.claims.exp<now{returnErr("Token expired".to_string());}// Check if session is still activeif!self.is_session_active(&token_data.claims.jti).await{returnErr("Session expired".to_string());}Ok(token_data.claims)}/// Check if user has permission.pubasyncfnhas_permission(&self,user_id:&str,permission:&str)->bool{ifletSome(user)=self.find_user_by_id(user_id).await{user.permissions.contains(&permission.to_string())}else{false}}/// Check if user has role.pubasyncfnhas_role(&self,user_id:&str,role:&str)->bool{ifletSome(user)=self.find_user_by_id(user_id).await{user.roles.contains(&role.to_string())}else{false}}/// Logout user.pubasyncfnlogout(&self,session_id:&str)->Result<(),String>{letmutsessions=self.user_sessions.write().await;sessions.remove(session_id);Ok(())}/// Hash password.fnhash_password(&self,password:&str)->Result<String,String>{letsalt=SaltString::generate(&mutOsRng);letpassword_hash=self.password_hasher.hash_password(password.as_bytes(),&salt).map_err(|e|format!("Failed to hash password: {}",e))?;Ok(password_hash.to_string())}/// Verify password.fnverify_password(&self,password:&str,hash:&str)->Result<bool,String>{letparsed_hash=PasswordHash::new(hash).map_err(|e|format!("Invalid password hash: {}",e))?;Ok(Argon2::default().verify_password(password.as_bytes(),&parsed_hash).is_ok())}/// Generate JWT token.fngenerate_jwt_token(&self,user:&User)->Result<String,String>{letnow=SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();letexp=now+self.jwt_expiry.as_secs();letclaims=JwtClaims{sub:user.id.clone(),username:user.username.clone(),roles:user.roles.clone(),permissions:user.permissions.clone(),iat:now,exp,jti:uuid::Uuid::new_v4().to_string(),};letheader=Header::new(Algorithm::HS256);letkey=EncodingKey::from_secret(self.jwt_secret.as_ref());encode(&header,&claims,&key).map_err(|e|format!("Failed to generate token: {}",e))}/// Generate refresh token.fngenerate_refresh_token(&self,user:&User)->Result<String,String>{// In a real implementation, you would generate a secure refresh tokenOk(uuid::Uuid::new_v4().to_string())}/// Check if user exists.asyncfnuser_exists(&self,username:&str,email:&str)->bool{// In a real implementation, check databasefalse}/// Store user.asyncfnstore_user(&self,user:&User)->Result<(),String>{// In a real implementation, store in databaseOk(())}/// Find user by username.asyncfnfind_user_by_username(&self,username:&str)->Option<User>{// In a real implementation, query databaseNone}/// Find user by ID.asyncfnfind_user_by_id(&self,user_id:&str)->Option<User>{// In a real implementation, query databaseNone}/// Store session.asyncfnstore_session(&self,session:&UserSession)->Result<(),String>{letmutsessions=self.user_sessions.write().await;sessions.insert(session.session_id.clone(),session.clone());Ok(())}/// Check if session is active.asyncfnis_session_active(&self,session_id:&str)->bool{letsessions=self.user_sessions.read().await;ifletSome(session)=sessions.get(session_id){session.is_active&&session.expires_at>Instant::now()}else{false}}/// Update last login.asyncfnupdate_last_login(&self,user_id:&str)->Result<(),String>{// In a real implementation, update databaseOk(())}/// Check rate limiting.asyncfnis_rate_limited(&self,ip_address:&str)->bool{letrate_limits=self.rate_limiter.read().await;ifletSome(info)=rate_limits.get(ip_address){ifletSome(blocked_until)=info.blocked_until{ifblocked_until>Instant::now(){returntrue;}}// Check if too many attempts in short timeifinfo.attempts>=5&&info.last_attempt.elapsed()<Duration::from_minutes(15){returntrue;}}false}/// Record failed attempt.asyncfnrecord_failed_attempt(&self,ip_address:&str){letmutrate_limits=self.rate_limiter.write().await;letinfo=rate_limits.entry(ip_address.to_string()).or_insert(RateLimitInfo{attempts:0,last_attempt:Instant::now(),blocked_until:None,});info.attempts+=1;info.last_attempt=Instant::now();ifinfo.attempts>=5{info.blocked_until=Some(Instant::now()+Duration::from_minutes(15));}}/// Clear rate limit.asyncfnclear_rate_limit(&self,ip_address:&str){letmutrate_limits=self.rate_limiter.write().await;rate_limits.remove(ip_address);}}#[cfg(test)]modtests{usesuper::*;#[tokio::test]asyncfntest_auth_manager(){letauth_manager=AuthManager::new("secret".to_string(),Duration::from_hours(1));letuser=auth_manager.register_user("testuser".to_string(),"test@example.com".to_string(),"password123".to_string(),).await.unwrap();assert_eq!(user.username,"testuser");assert_eq!(user.email,"test@example.com");}#[tokio::test]asyncfntest_authentication(){letauth_manager=AuthManager::new("secret".to_string(),Duration::from_hours(1));letrequest=LoginRequest{username:"testuser".to_string(),password:"password123".to_string(),ip_address:"127.0.0.1".to_string(),user_agent:"test".to_string(),};// This would fail in real implementation without proper user setupletresult=auth_manager.authenticate(request).await;assert!(result.is_err());}}
// rust/03-data-encryption.rs/*Data encryption patterns and best practices*/usestd::collections::HashMap;usestd::sync::Arc;usestd::time::{Duration,Instant};usetokio::sync::RwLock;useserde::{Deserialize,Serialize};useaes_gcm::{Aes256Gcm,Key,Nonce};useaes_gcm::aead::{Aead,NewAead};usechacha20poly1305::{ChaCha20Poly1305,KeyasChaChaKey,NonceasChaChaNonce};usechacha20poly1305::aead::{AeadasChaChaAead,NewAeadasChaChaNewAead};/// Encryption manager.pubstructEncryptionManager{aes_key:Key<Aes256Gcm>,chacha_key:ChaChaKey<ChaCha20Poly1305>,key_rotation_interval:Duration,last_key_rotation:Instant,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructEncryptedData{pubdata:Vec<u8>,pubalgorithm:String,pubkey_id:String,pubnonce:Vec<u8>,pubtag:Vec<u8>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructEncryptionConfig{pubalgorithm:EncryptionAlgorithm,pubkey_size:usize,pubnonce_size:usize,pubtag_size:usize,pubkey_rotation_interval:Duration,}#[derive(Debug, Clone, Serialize, Deserialize)]pubenumEncryptionAlgorithm{Aes256Gcm,ChaCha20Poly1305,}implEncryptionManager{pubfnnew()->Self{letaes_key=Key::<Aes256Gcm>::from_slice(b"01234567890123456789012345678901");letchacha_key=ChaChaKey::<ChaCha20Poly1305>::from_slice(b"01234567890123456789012345678901");Self{aes_key:*aes_key,chacha_key:*chacha_key,key_rotation_interval:Duration::from_days(30),last_key_rotation:Instant::now(),}}/// Encrypt data using AES-256-GCM.pubfnencrypt_aes(&self,data:&[u8])->Result<EncryptedData,String>{letcipher=Aes256Gcm::new(&self.aes_key);letnonce=Nonce::from_slice(b"012345678901");// 12 bytes for GCMletencrypted_data=cipher.encrypt(nonce,data).map_err(|e|format!("Encryption failed: {}",e))?;Ok(EncryptedData{data:encrypted_data,algorithm:"AES-256-GCM".to_string(),key_id:"default".to_string(),nonce:nonce.to_vec(),tag:Vec::new(),// GCM includes tag in encrypted data})}/// Decrypt data using AES-256-GCM.pubfndecrypt_aes(&self,encrypted_data:&EncryptedData)->Result<Vec<u8>,String>{letcipher=Aes256Gcm::new(&self.aes_key);letnonce=Nonce::from_slice(&encrypted_data.nonce);letdecrypted_data=cipher.decrypt(nonce,&encrypted_data.data).map_err(|e|format!("Decryption failed: {}",e))?;Ok(decrypted_data)}/// Encrypt data using ChaCha20-Poly1305.pubfnencrypt_chacha(&self,data:&[u8])->Result<EncryptedData,String>{letcipher=ChaCha20Poly1305::new(&self.chacha_key);letnonce=ChaChaNonce::from_slice(b"012345678901");// 12 bytes for ChaCha20-Poly1305letencrypted_data=cipher.encrypt(nonce,data).map_err(|e|format!("Encryption failed: {}",e))?;Ok(EncryptedData{data:encrypted_data,algorithm:"ChaCha20-Poly1305".to_string(),key_id:"default".to_string(),nonce:nonce.to_vec(),tag:Vec::new(),// ChaCha20-Poly1305 includes tag in encrypted data})}/// Decrypt data using ChaCha20-Poly1305.pubfndecrypt_chacha(&self,encrypted_data:&EncryptedData)->Result<Vec<u8>,String>{letcipher=ChaCha20Poly1305::new(&self.chacha_key);letnonce=ChaChaNonce::from_slice(&encrypted_data.nonce);letdecrypted_data=cipher.decrypt(nonce,&encrypted_data.data).map_err(|e|format!("Decryption failed: {}",e))?;Ok(decrypted_data)}/// Encrypt data with automatic algorithm selection.pubfnencrypt(&self,data:&[u8],algorithm:EncryptionAlgorithm)->Result<EncryptedData,String>{matchalgorithm{EncryptionAlgorithm::Aes256Gcm=>self.encrypt_aes(data),EncryptionAlgorithm::ChaCha20Poly1305=>self.encrypt_chacha(data),}}/// Decrypt data with automatic algorithm detection.pubfndecrypt(&self,encrypted_data:&EncryptedData)->Result<Vec<u8>,String>{matchencrypted_data.algorithm.as_str(){"AES-256-GCM"=>self.decrypt_aes(encrypted_data),"ChaCha20-Poly1305"=>self.decrypt_chacha(encrypted_data),_=>Err("Unsupported encryption algorithm".to_string()),}}/// Encrypt sensitive fields in a struct.pubfnencrypt_struct<T>(&self,data:&T,fields:&[String])->Result<HashMap<String,EncryptedData>,String>whereT:Serialize,{letjson=serde_json::to_value(data).map_err(|e|format!("Serialization failed: {}",e))?;letmutencrypted_fields=HashMap::new();ifletSome(obj)=json.as_object(){forfieldinfields{ifletSome(value)=obj.get(field){letfield_data=serde_json::to_vec(value).map_err(|e|format!("Field serialization failed: {}",e))?;letencrypted=self.encrypt(&field_data,EncryptionAlgorithm::Aes256Gcm)?;encrypted_fields.insert(field.clone(),encrypted);}}}Ok(encrypted_fields)}/// Decrypt sensitive fields in a struct.pubfndecrypt_struct<T>(&self,encrypted_fields:&HashMap<String,EncryptedData>)->Result<HashMap<String,serde_json::Value>,String>whereT:Deserialize<'static>,{letmutdecrypted_fields=HashMap::new();for(field,encrypted_data)inencrypted_fields{letdecrypted_data=self.decrypt(encrypted_data)?;letvalue:serde_json::Value=serde_json::from_slice(&decrypted_data).map_err(|e|format!("Deserialization failed: {}",e))?;decrypted_fields.insert(field.clone(),value);}Ok(decrypted_fields)}/// Check if key rotation is needed.pubfnneeds_key_rotation(&self)->bool{self.last_key_rotation.elapsed()>=self.key_rotation_interval}/// Rotate encryption keys.pubfnrotate_keys(&mutself)->Result<(),String>{// In a real implementation, generate new keys and update key storeself.last_key_rotation=Instant::now();Ok(())}/// Generate secure random key.pubfngenerate_key(&self,size:usize)->Result<Vec<u8>,String>{userand::RngCore;letmutkey=vec![0u8;size];rand::thread_rng().fill_bytes(&mutkey);Ok(key)}/// Generate secure random nonce.pubfngenerate_nonce(&self,size:usize)->Result<Vec<u8>,String>{userand::RngCore;letmutnonce=vec![0u8;size];rand::thread_rng().fill_bytes(&mutnonce);Ok(nonce)}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_aes_encryption(){letmanager=EncryptionManager::new();letdata=b"Hello, World!";letencrypted=manager.encrypt_aes(data).unwrap();letdecrypted=manager.decrypt_aes(&encrypted).unwrap();assert_eq!(decrypted,data);}#[test]fntest_chacha_encryption(){letmanager=EncryptionManager::new();letdata=b"Hello, World!";letencrypted=manager.encrypt_chacha(data).unwrap();letdecrypted=manager.decrypt_chacha(&encrypted).unwrap();assert_eq!(decrypted,data);}#[test]fntest_automatic_encryption(){letmanager=EncryptionManager::new();letdata=b"Hello, World!";letencrypted=manager.encrypt(data,EncryptionAlgorithm::Aes256Gcm).unwrap();letdecrypted=manager.decrypt(&encrypted).unwrap();assert_eq!(decrypted,data);}}