- Created SelfFreezoneClient in Self components
- Wraps SDK FreezoneScriptClient for Self-specific operations
- Implements send_verification_email method
- Uses Rhai script template for email verification
- Includes template variable substitution
- Added serde-wasm-bindgen dependency
Usage:
let client = SelfFreezoneClient::builder()
.supervisor_url("http://localhost:8080")
.secret("my-secret")
.build()?;
client.send_verification_email(
"user@example.com",
"123456",
"https://verify.com/abc"
).await?;
15 KiB
15 KiB
Security Model
Overview
Self implements a comprehensive security model based on self-sovereign identity principles, cryptographic authentication, and zero-knowledge architecture. The security model prioritizes user control, data minimization, and defense in depth.
Security Principles
1. Self-Sovereign Identity
- User Control: Users generate and control their own cryptographic keys
- No Central Authority: No single point of failure or control
- Decentralized Trust: Trust distributed across cryptographic proofs
- Data Ownership: Users own and control their identity data
2. Zero-Knowledge Architecture
- Client-Side Encryption: All sensitive operations performed locally
- No Server Secrets: Server never sees private keys or passwords
- Minimal Data Collection: Only necessary public information stored
- Cryptographic Proofs: Authentication without revealing secrets
3. Defense in Depth
- Multiple Security Layers: Transport, application, and storage security
- Fail-Safe Defaults: Secure by default configuration
- Principle of Least Privilege: Minimal necessary permissions
- Security Monitoring: Comprehensive logging and monitoring
Threat Model
Assets to Protect
- Private Keys: User's cryptographic private keys
- Passwords: User-chosen encryption passwords
- Identity Data: Personal information and metadata
- Session Tokens: Authentication tokens and sessions
- Communication: Data in transit between client and server
Threat Actors
1. External Attackers
- Capabilities: Network access, public endpoints
- Motivations: Identity theft, financial gain, disruption
- Attack Vectors: Network attacks, social engineering, malware
2. Malicious Insiders
- Capabilities: Server access, code modification
- Motivations: Data theft, sabotage, espionage
- Attack Vectors: Privilege abuse, backdoors, data exfiltration
3. Nation-State Actors
- Capabilities: Advanced persistent threats, zero-days
- Motivations: Surveillance, intelligence gathering
- Attack Vectors: Supply chain attacks, infrastructure compromise
4. Compromised Infrastructure
- Capabilities: Server compromise, DNS hijacking
- Motivations: Data theft, service disruption
- Attack Vectors: Infrastructure attacks, certificate compromise
Attack Scenarios
Scenario 1: Private Key Theft
Attack: Malware extracts encrypted private keys from localStorage
Threat: Malware on user device
Impact: Identity compromise if password is weak
Mitigation: Strong encryption, password requirements
Residual Risk: Weak user passwords
Scenario 2: Server Compromise
Attack: Attacker gains full server access
Threat: Server infrastructure compromise
Impact: User data exposure, service disruption
Mitigation: No private keys on server, encrypted storage
Residual Risk: Public key and email exposure
Scenario 3: Man-in-the-Middle
Attack: Network traffic interception and modification
Threat: Network-level attacker
Impact: Authentication bypass, data theft
Mitigation: HTTPS, certificate pinning, signature verification
Residual Risk: Certificate authority compromise
Scenario 4: Social Engineering
Attack: Trick user into revealing password or private key
Threat: Social engineering attack
Impact: Full identity compromise
Mitigation: User education, secure key handling
Residual Risk: User susceptibility to social engineering
Security Controls
Cryptographic Controls
1. Key Generation
// Secure random number generation
use getrandom::getrandom;
fn generate_secure_key() -> Result<[u8; 32], CryptoError> {
let mut key = [0u8; 32];
getrandom(&mut key)?;
// Validate key is not weak
if key.iter().all(|&b| b == 0) {
return Err(CryptoError::WeakKey);
}
Ok(key)
}
Controls:
- Cryptographically secure random number generation
- Key validation to prevent weak keys
- Proper entropy collection from OS
2. Encryption
// AES-256-GCM with proper nonce handling
use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
fn encrypt_data(data: &[u8], key: &[u8; 32]) -> Result<EncryptedData, CryptoError> {
let cipher = Aes256Gcm::new(Key::from_slice(key));
// Generate random nonce
let mut nonce_bytes = [0u8; 12];
getrandom(&mut nonce_bytes)?;
let nonce = Nonce::from_slice(&nonce_bytes);
let ciphertext = cipher.encrypt(nonce, data)?;
Ok(EncryptedData {
ciphertext,
nonce: nonce_bytes,
})
}
Controls:
- AES-256-GCM authenticated encryption
- Random nonce generation for each encryption
- Authenticated encryption prevents tampering
3. Key Derivation
// PBKDF2 with configurable iterations
use pbkdf2::{pbkdf2_hmac};
use sha2::Sha256;
fn derive_key(password: &str, salt: &[u8], iterations: u32) -> [u8; 32] {
let mut key = [0u8; 32];
pbkdf2_hmac::<Sha256>(password.as_bytes(), salt, iterations, &mut key);
key
}
Controls:
- PBKDF2 with SHA-256 for key derivation
- Configurable iteration count (minimum 10,000)
- Random salt for each key derivation
Access Controls
1. Authentication
pub enum AuthenticationLevel {
None, // No authentication required
PublicKey, // Public key verification only
Signature, // Cryptographic signature required
Password, // Password-based access
}
impl AccessControl {
pub fn check_authentication(&self, level: AuthenticationLevel) -> Result<(), AuthError> {
match level {
AuthenticationLevel::None => Ok(()),
AuthenticationLevel::PublicKey => self.verify_public_key(),
AuthenticationLevel::Signature => self.verify_signature(),
AuthenticationLevel::Password => self.verify_password(),
}
}
}
2. Authorization
pub struct Permission {
pub resource: String,
pub action: String,
pub conditions: Vec<String>,
}
impl Authorization {
pub fn check_permission(&self, user: &User, permission: &Permission) -> bool {
// Check if user has required permission
self.user_permissions.get(&user.id)
.map(|perms| perms.contains(permission))
.unwrap_or(false)
}
}
Network Security
1. Transport Layer Security
// HTTPS configuration
use axum_server::tls_rustls::RustlsConfig;
async fn create_tls_server() -> Result<(), ServerError> {
let config = RustlsConfig::from_pem_file(
PathBuf::from("cert.pem"),
PathBuf::from("key.pem"),
).await?;
let app = create_app();
axum_server::bind_rustls("0.0.0.0:443".parse()?, config)
.serve(app.into_make_service())
.await?;
Ok(())
}
Controls:
- TLS 1.3 for all communications
- Certificate validation and pinning
- HSTS headers for HTTPS enforcement
2. CORS Configuration
use tower_http::cors::{CorsLayer, Any};
fn configure_cors() -> CorsLayer {
CorsLayer::new()
.allow_origin(Any) // Configure for production
.allow_methods([Method::GET, Method::POST])
.allow_headers([header::CONTENT_TYPE, header::AUTHORIZATION])
.allow_credentials(false)
}
Application Security
1. Input Validation
use validator::{Validate, ValidationError};
#[derive(Validate)]
pub struct RegistrationRequest {
#[validate(email)]
pub email: String,
#[validate(length(min = 1, max = 100))]
pub name: String,
#[validate(custom = "validate_public_key")]
pub public_key: String,
}
fn validate_public_key(public_key: &str) -> Result<(), ValidationError> {
if !is_valid_hex(public_key) || public_key.len() != 130 {
return Err(ValidationError::new("invalid_public_key"));
}
Ok(())
}
2. Error Handling
pub enum SecurityError {
InvalidInput(String),
AuthenticationFailed,
AuthorizationDenied,
CryptographicError(String),
RateLimitExceeded,
}
impl SecurityError {
pub fn safe_message(&self) -> &'static str {
match self {
SecurityError::InvalidInput(_) => "Invalid input provided",
SecurityError::AuthenticationFailed => "Authentication failed",
SecurityError::AuthorizationDenied => "Access denied",
SecurityError::CryptographicError(_) => "Cryptographic operation failed",
SecurityError::RateLimitExceeded => "Rate limit exceeded",
}
}
}
Storage Security
1. Client-Side Storage
// Secure localStorage usage
pub struct SecureStorage {
prefix: String,
}
impl SecureStorage {
pub fn store_encrypted(&self, key: &str, data: &EncryptedData) -> Result<(), StorageError> {
let storage_key = format!("{}_{}", self.prefix, key);
let serialized = serde_json::to_string(data)?;
web_sys::window()
.and_then(|w| w.local_storage().ok().flatten())
.ok_or(StorageError::NotAvailable)?
.set_item(&storage_key, &serialized)
.map_err(|_| StorageError::WriteFailed)?;
Ok(())
}
}
2. Server-Side Storage
// Minimal server storage
pub struct UserRecord {
pub id: String,
pub email: String, // Not sensitive
pub public_key: String, // Public by definition
pub name: String, // User-provided, not sensitive
pub created_at: String, // Timestamp, not sensitive
// Note: No private keys or passwords stored
}
Security Monitoring
Logging Strategy
1. Security Events
use tracing::{info, warn, error};
pub fn log_authentication_attempt(public_key: &str, success: bool) {
if success {
info!(
event = "authentication_success",
public_key = %public_key[..8], // Log only prefix
timestamp = %Utc::now()
);
} else {
warn!(
event = "authentication_failure",
public_key = %public_key[..8],
timestamp = %Utc::now()
);
}
}
2. Anomaly Detection
pub struct SecurityMonitor {
failed_attempts: HashMap<String, Vec<DateTime<Utc>>>,
rate_limits: HashMap<String, RateLimit>,
}
impl SecurityMonitor {
pub fn check_suspicious_activity(&mut self, public_key: &str) -> bool {
let now = Utc::now();
let attempts = self.failed_attempts.entry(public_key.to_string()).or_default();
// Remove old attempts (older than 1 hour)
attempts.retain(|&time| now.signed_duration_since(time).num_hours() < 1);
// Check if too many recent failures
attempts.len() > 5
}
}
Metrics Collection
1. Security Metrics
use prometheus::{Counter, Histogram, Gauge};
lazy_static! {
static ref AUTH_ATTEMPTS: Counter = Counter::new(
"auth_attempts_total", "Total authentication attempts"
).unwrap();
static ref AUTH_FAILURES: Counter = Counter::new(
"auth_failures_total", "Total authentication failures"
).unwrap();
static ref CRYPTO_OPERATIONS: Histogram = Histogram::new(
"crypto_operation_duration_seconds", "Cryptographic operation duration"
).unwrap();
}
Incident Response
Security Incident Types
1. Key Compromise
Response Procedure:
- Immediately revoke affected tokens
- Notify user through secure channel
- Guide user through key rotation process
- Monitor for unauthorized usage
- Update security controls if needed
2. Server Compromise
Response Procedure:
- Isolate affected systems
- Assess scope of compromise
- Rotate server secrets and certificates
- Notify users of potential impact
- Implement additional monitoring
3. Vulnerability Discovery
Response Procedure:
- Assess vulnerability severity
- Develop and test fix
- Deploy fix to production
- Notify users if necessary
- Conduct post-incident review
Recovery Procedures
1. Key Recovery
pub struct KeyRecovery {
pub backup_methods: Vec<BackupMethod>,
pub recovery_contacts: Vec<String>,
}
pub enum BackupMethod {
ExportedVault,
PaperBackup,
HardwareToken,
SocialRecovery,
}
2. Service Recovery
pub struct ServiceRecovery {
pub backup_servers: Vec<String>,
pub database_backups: Vec<BackupInfo>,
pub recovery_time_objective: Duration,
pub recovery_point_objective: Duration,
}
Compliance and Auditing
Regulatory Compliance
1. GDPR Compliance
- Right to Access: Users can export their data
- Right to Rectification: Users can update their information
- Right to Erasure: Users can delete their accounts
- Data Portability: Vault export functionality
- Privacy by Design: Minimal data collection
2. SOX Compliance
- Access Controls: Role-based access control
- Audit Trails: Comprehensive logging
- Data Integrity: Cryptographic verification
- Change Management: Controlled deployment process
Security Auditing
1. Code Auditing
// Security-focused code review checklist
pub struct SecurityAudit {
pub crypto_review: bool, // Cryptographic implementation review
pub input_validation: bool, // Input validation coverage
pub error_handling: bool, // Secure error handling
pub access_control: bool, // Authorization checks
pub logging_review: bool, // Security logging adequacy
}
2. Penetration Testing
- Network Security: External network testing
- Application Security: Web application testing
- Client Security: Browser-based testing
- Social Engineering: User awareness testing
Security Best Practices
Development Security
-
Secure Coding Standards
- Input validation on all user inputs
- Output encoding for all outputs
- Proper error handling without information leakage
- Secure random number generation
-
Code Review Process
- Security-focused peer reviews
- Automated security scanning
- Cryptographic implementation review
- Third-party security audits
-
Testing Strategy
- Unit tests for security functions
- Integration tests for auth flows
- Penetration testing
- Fuzzing for input validation
Deployment Security
-
Infrastructure Security
- Hardened server configurations
- Network segmentation
- Intrusion detection systems
- Regular security updates
-
Configuration Management
- Secure default configurations
- Environment-specific settings
- Secret management systems
- Configuration validation
Operational Security
-
Monitoring and Alerting
- Real-time security monitoring
- Automated threat detection
- Incident response procedures
- Regular security assessments
-
User Education
- Security awareness training
- Best practice documentation
- Phishing awareness
- Incident reporting procedures