saorsa_core/identity/
manager.rs

1//! Identity Manager
2//! 
3//! Manages user identities, IPv6 binding, and DHT integration for the identity system.
4
5use crate::{P2PError, Result, dht::Key, security::IPv6NodeID};
6use ed25519_dalek::{PublicKey as Ed25519PublicKey, Keypair, Signer};
7use serde::{Deserialize, Serialize};
8use std::time::SystemTime;
9use tracing::info;
10
11// Core identity types
12
13/// Unique identifier for users in the P2P system
14/// 
15/// User IDs are derived from public keys using SHA-256 hashing to ensure
16/// uniqueness and prevent impersonation. They serve as the primary identifier
17/// for all user-related operations in the DHT and network layer.
18pub type UserId = String;
19
20/// Basic user identity containing core identification information
21/// 
22/// This struct represents the fundamental identity of a user in the P2P system.
23/// It contains cryptographic proof of identity, addressing information, and
24/// verification status. The identity is designed to be lightweight and can be
25/// shared publicly without revealing sensitive personal information.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct UserIdentity {
28    /// Unique identifier derived from the user's public key
29    pub user_id: UserId,
30    /// Ed25519 public key for signature verification and encryption
31    pub public_key: Vec<u8>,
32    /// Truncated display name (first 20 chars) for privacy protection
33    pub display_name_hint: String,
34    /// Human-readable three-word address for easy network identification
35    pub three_word_address: String,
36    /// Timestamp when this identity was created
37    pub created_at: SystemTime,
38    /// Version number for identity updates and compatibility
39    pub version: u32,
40    /// Current verification status of this identity
41    pub verification_level: VerificationLevel,
42}
43
44/// Encrypted user profile for secure DHT storage
45/// 
46/// Contains encrypted personal information and profile data that is stored
47/// in the DHT. The encryption ensures that only authorized parties can access
48/// the full profile information while still allowing network verification.
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct EncryptedUserProfile {
51    /// User identifier matching the identity
52    pub user_id: UserId,
53    /// Public key for verification and key exchange
54    pub public_key: Vec<u8>,
55    /// AES-GCM encrypted profile data containing personal information
56    pub encrypted_data: Vec<u8>,
57    /// Ed25519 signature of the encrypted data for integrity verification
58    pub signature: Vec<u8>,
59    /// Optional proof of IPv6 address binding for network verification
60    pub ipv6_binding_proof: Option<IPv6BindingProof>,
61    /// Timestamp when this profile was created
62    pub created_at: SystemTime,
63}
64
65/// IPv6 binding proof for network verification
66/// 
67/// Proves that a user identity is bound to a specific IPv6 address,
68/// preventing network-level impersonation and enabling secure peer-to-peer
69/// communication. The proof is cryptographically signed and time-stamped.
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct IPv6BindingProof {
72    /// The IPv6 address being bound to the identity
73    pub ipv6_address: String,
74    /// Ed25519 signature proving ownership of both the identity and IPv6 address
75    pub signature: Vec<u8>,
76    /// Timestamp when the binding was created for freshness verification
77    pub timestamp: SystemTime,
78}
79
80impl IPv6BindingProof {
81    /// Create new IPv6 binding proof
82    pub fn new(
83        ipv6_id: IPv6NodeID,
84        user_keypair: &Keypair,
85        ipv6_keypair: &Keypair,
86    ) -> Result<Self> {
87        let ipv6_address = format!("{:?}", ipv6_id); // Placeholder conversion
88        let timestamp = SystemTime::now();
89        
90        // Create signature data (simplified)
91        let signature_data = format!("{}:{}", ipv6_address, 
92            timestamp.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs());
93        let signature = user_keypair.sign(signature_data.as_bytes()).to_bytes().to_vec();
94        
95        Ok(Self {
96            ipv6_address,
97            signature,
98            timestamp,
99        })
100    }
101}
102
103/// Access grant for profile sharing and permissions
104/// 
105/// Represents a time-limited permission grant allowing specific access
106/// to user profile information. Used for implementing fine-grained
107/// privacy controls and temporary access delegation.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct AccessGrant {
110    /// User ID that granted the access
111    pub user_id: UserId,
112    /// List of permission strings defining what access is granted
113    pub permissions: Vec<String>,
114    /// Timestamp when the grant was issued
115    pub granted_at: SystemTime,
116    /// Timestamp when the grant expires
117    pub expires_at: SystemTime,
118}
119
120/// Challenge response for identity verification
121/// 
122/// Used in challenge-response authentication protocols to prove
123/// ownership of a private key without revealing it. Essential for
124/// secure peer authentication and preventing replay attacks.
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct ChallengeResponse {
127    /// Unique identifier for the challenge being responded to
128    pub challenge_id: String,
129    /// Ed25519 signature of the challenge data
130    pub signature: Vec<u8>,
131    /// Additional response data specific to the challenge type
132    pub response_data: Vec<u8>,
133}
134
135/// Comprehensive user profile information
136/// 
137/// Contains all personal and preference information for a user. This data
138/// is stored encrypted in the DHT and can be selectively shared based on
139/// privacy settings and access grants. Supports extensibility through custom fields.
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct UserProfile {
142    /// Unique user identifier matching the identity
143    pub user_id: UserId,
144    /// User's chosen display name (can be different from hint in identity)
145    pub display_name: String,
146    /// Optional biographical information or description
147    pub bio: Option<String>,
148    /// Optional URL to user's avatar image
149    pub avatar_url: Option<String>,
150    /// Optional hash of avatar image for integrity verification
151    pub avatar_hash: Option<String>,
152    /// Optional current status message
153    pub status_message: Option<String>,
154    /// User's public key for verification (matches identity)
155    pub public_key: Vec<u8>,
156    /// User preferences for behavior and privacy
157    pub preferences: UserPreferences,
158    /// Extensible custom fields for application-specific data
159    pub custom_fields: std::collections::HashMap<String, serde_json::Value>,
160    /// Timestamp when profile was created
161    pub created_at: SystemTime,
162    /// Timestamp when profile was last updated
163    pub updated_at: SystemTime,
164}
165
166impl UserProfile {
167    /// Create new user profile with default settings
168    /// 
169    /// # Arguments
170    /// * `display_name` - The user's chosen display name
171    /// 
172    /// # Returns
173    /// A new UserProfile with default preferences and empty optional fields
174    pub fn new(display_name: String) -> Self {
175        let now = SystemTime::now();
176        Self {
177            user_id: String::new(), // Will be set when associated with identity
178            display_name,
179            bio: None,
180            avatar_url: None,
181            avatar_hash: None,
182            status_message: None,
183            public_key: Vec::new(), // Will be set when associated with identity
184            preferences: UserPreferences::default(),
185            custom_fields: std::collections::HashMap::new(),
186            created_at: now,
187            updated_at: now,
188        }
189    }
190    
191    /// Update the profile's last modified timestamp
192    /// 
193    /// Should be called whenever any profile data is modified to maintain
194    /// accurate synchronization information.
195    pub fn update(&mut self) {
196        self.updated_at = SystemTime::now();
197    }
198}
199
200impl UserIdentity {
201    /// Create new user identity with cryptographic keypair
202    /// 
203    /// Generates a new Ed25519 keypair and creates a corresponding user identity.
204    /// The user ID is derived from the public key to ensure uniqueness.
205    /// 
206    /// # Arguments
207    /// * `display_name` - Full display name (will be truncated for hint)
208    /// * `three_word_address` - Human-readable three-word network address
209    /// 
210    /// # Returns
211    /// A tuple containing the new identity and its associated keypair
212    /// 
213    /// # Errors
214    /// Returns error if cryptographic key generation fails
215    pub fn new(display_name: String, three_word_address: String) -> Result<(Self, Keypair)> {
216        use rand_core::OsRng;
217        
218        // Generate new keypair
219        let mut csprng = OsRng;
220        let keypair = Keypair::generate(&mut csprng);
221        
222        // Derive user ID from public key
223        let user_id = Self::derive_user_id(&keypair.public);
224        
225        // Create display name hint
226        let display_name_hint = Self::create_display_name_hint(&display_name);
227        
228        let identity = Self {
229            user_id,
230            public_key: keypair.public.as_bytes().to_vec(),
231            display_name_hint,
232            three_word_address,
233            created_at: SystemTime::now(),
234            version: 1,
235            verification_level: VerificationLevel::SelfSigned,
236        };
237        
238        Ok((identity, keypair))
239    }
240    
241    /// Derive deterministic user ID from public key
242    /// 
243    /// Uses SHA-256 hash of the public key to create a unique, deterministic
244    /// user identifier. This ensures the same public key always produces
245    /// the same user ID.
246    /// 
247    /// # Arguments
248    /// * `public_key` - Ed25519 public key to derive ID from
249    /// 
250    /// # Returns
251    /// Hexadecimal string representation of the SHA-256 hash
252    pub fn derive_user_id(public_key: &Ed25519PublicKey) -> UserId {
253        use sha2::{Sha256, Digest};
254        let mut hasher = Sha256::new();
255        hasher.update(public_key.as_bytes());
256        hex::encode(hasher.finalize())
257    }
258    
259    /// Create privacy-preserving display name hint
260    /// 
261    /// Truncates the full display name to the first 20 characters to provide
262    /// a hint for identification while preserving privacy. This prevents
263    /// full name disclosure in public identity records.
264    /// 
265    /// # Arguments
266    /// * `display_name` - Full display name to create hint from
267    /// 
268    /// # Returns
269    /// Truncated display name (max 20 characters)
270    pub fn create_display_name_hint(display_name: &str) -> String {
271        // Take first 20 characters to avoid revealing full names
272        display_name.chars().take(20).collect()
273    }
274    
275    /// Get DHT storage key for this identity's profile
276    /// 
277    /// Creates a deterministic DHT key based on the user ID for storing
278    /// and retrieving the encrypted user profile from the distributed hash table.
279    /// 
280    /// # Returns
281    /// DHT key for profile storage location
282    pub fn get_profile_dht_key(&self) -> Key {
283        Key::new(format!("user_profile:{}", self.user_id).as_bytes())
284    }
285}
286
287impl EncryptedUserProfile {
288    /// Create new encrypted user profile from raw cryptographic data
289    /// 
290    /// # Arguments
291    /// * `user_id` - User identifier matching an existing identity
292    /// * `public_key` - Ed25519 public key bytes for verification
293    /// * `encrypted_data` - AES-GCM encrypted profile data
294    /// * `signature` - Ed25519 signature of the encrypted data
295    /// 
296    /// # Returns
297    /// New encrypted profile instance with current timestamp
298    pub fn new(
299        user_id: UserId,
300        public_key: Vec<u8>,
301        encrypted_data: Vec<u8>,
302        signature: Vec<u8>,
303    ) -> Self {
304        Self {
305            user_id,
306            public_key,
307            encrypted_data,
308            signature,
309            ipv6_binding_proof: None,
310            created_at: SystemTime::now(),
311        }
312    }
313    
314    /// Create encrypted user profile from identity and profile data
315    /// 
316    /// Encrypts a user profile and creates cryptographic signatures for secure
317    /// storage in the DHT. Optionally includes IPv6 binding proof.
318    /// 
319    /// # Arguments
320    /// * `identity` - User identity to associate with the profile
321    /// * `profile` - Unencrypted profile data to be secured
322    /// * `keypair` - Ed25519 keypair for signing operations
323    /// * `ipv6_binding` - Optional IPv6 address binding proof
324    /// 
325    /// # Returns
326    /// Encrypted and signed profile ready for DHT storage
327    /// 
328    /// # Errors
329    /// Returns error if serialization or signing fails
330    pub fn new_from_identity(
331        identity: &UserIdentity,
332        profile: &UserProfile,
333        keypair: &Keypair,
334        ipv6_binding: Option<IPv6BindingProof>,
335    ) -> Result<Self> {
336        // Serialize the profile data
337        let profile_data = serde_json::to_vec(profile)
338            .map_err(|e| P2PError::Serialization(e))?;
339        
340        // Generate encryption key from keypair deterministically
341        use sha2::{Sha256, Digest};
342        let mut hasher = Sha256::new();
343        hasher.update(&keypair.to_bytes());
344        hasher.update(b"profile-encryption-key");
345        let encryption_key = hasher.finalize();
346        
347        // Encrypt the profile data using AES-GCM
348        let encrypted_data = Self::encrypt_profile_data(&profile_data, &encryption_key)?;
349        
350        // Create signature of the encrypted data
351        let signature = keypair.sign(&encrypted_data).to_bytes().to_vec();
352        
353        Ok(Self {
354            user_id: identity.user_id.clone(),
355            public_key: identity.public_key.clone(),
356            encrypted_data,
357            signature,
358            ipv6_binding_proof: ipv6_binding,
359            created_at: SystemTime::now(),
360        })
361    }
362    
363    /// Generate random 256-bit AES key for profile encryption
364    /// 
365    /// Creates a cryptographically secure random key for encrypting
366    /// profile data. Each profile should have its own unique key.
367    /// 
368    /// # Returns
369    /// 32-byte AES-256 encryption key
370    pub fn generate_profile_key() -> [u8; 32] {
371        rand::random()
372    }
373    
374    /// Verify the cryptographic signature of the encrypted profile
375    /// 
376    /// Validates that the signature was created by the holder of the
377    /// private key corresponding to the stored public key.
378    /// 
379    /// # Returns
380    /// True if signature is valid, false otherwise
381    /// 
382    /// # Errors
383    /// Returns error if signature verification fails
384    pub fn verify_signature(&self) -> Result<bool> {
385        use ed25519_dalek::{PublicKey, Signature, Verifier};
386        
387        // Parse the public key
388        let public_key = PublicKey::from_bytes(&self.public_key)
389            .map_err(|e| P2PError::Identity(format!("Invalid public key: {}", e)))?;
390        
391        // Parse the signature
392        let signature = Signature::from_bytes(&self.signature)
393            .map_err(|e| P2PError::Identity(format!("Invalid signature: {}", e)))?;
394        
395        // Verify signature against encrypted data
396        match public_key.verify(&self.encrypted_data, &signature) {
397            Ok(()) => Ok(true),
398            Err(_) => Ok(false),
399        }
400    }
401    
402    /// Encrypt profile data using AES-GCM
403    fn encrypt_profile_data(data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
404        use aes_gcm::{Aes256Gcm, Key, Nonce, AeadInPlace, KeyInit};
405        use rand::RngCore;
406        
407        if key.len() != 32 {
408            return Err(P2PError::Identity("Invalid encryption key length - must be 32 bytes".to_string()));
409        }
410        
411        let cipher_key = aes_gcm::Key::<Aes256Gcm>::from_slice(key);
412        let cipher = Aes256Gcm::new(cipher_key);
413        
414        // Generate random 96-bit nonce
415        let mut nonce_bytes = [0u8; 12];
416        rand::thread_rng().fill_bytes(&mut nonce_bytes);
417        let nonce = Nonce::from_slice(&nonce_bytes);
418        
419        // Encrypt the data
420        let mut ciphertext = data.to_vec();
421        let tag = cipher.encrypt_in_place_detached(nonce, b"", &mut ciphertext)
422            .map_err(|e| P2PError::Identity(format!("Profile encryption failed: {}", e)))?;
423        
424        // Combine nonce + ciphertext + tag
425        let mut result = Vec::with_capacity(12 + ciphertext.len() + 16);
426        result.extend_from_slice(&nonce_bytes);
427        result.extend_from_slice(&ciphertext);
428        result.extend_from_slice(&tag);
429        
430        Ok(result)
431    }
432    
433    /// Decrypt profile data using AES-GCM
434    fn decrypt_profile_data(encrypted: &[u8], key: &[u8]) -> Result<Vec<u8>> {
435        use aes_gcm::{Aes256Gcm, Key, Nonce, AeadInPlace, KeyInit};
436        
437        if key.len() != 32 {
438            return Err(P2PError::Identity("Invalid decryption key length - must be 32 bytes".to_string()));
439        }
440        
441        if encrypted.len() < 28 {
442            return Err(P2PError::Identity("Invalid encrypted profile data - too short".to_string()));
443        }
444        
445        let cipher_key = aes_gcm::Key::<Aes256Gcm>::from_slice(key);
446        let cipher = Aes256Gcm::new(cipher_key);
447        
448        // Extract components
449        let nonce = Nonce::from_slice(&encrypted[0..12]);
450        let tag_start = encrypted.len() - 16;
451        let tag = &encrypted[tag_start..];
452        let mut plaintext = encrypted[12..tag_start].to_vec();
453        
454        // Decrypt the data
455        cipher.decrypt_in_place_detached(nonce, b"", &mut plaintext, tag.into())
456            .map_err(|e| P2PError::Identity(format!("Profile decryption failed: {}", e)))?;
457        
458        Ok(plaintext)
459    }
460    
461    /// Decrypt the encrypted profile data using provided key
462    /// 
463    /// Decrypts the AES-GCM encrypted profile data to recover the original
464    /// UserProfile structure. Requires the correct decryption key.
465    /// 
466    /// # Arguments
467    /// * `key` - AES-256 decryption key (32 bytes)
468    /// 
469    /// # Returns
470    /// Decrypted UserProfile structure
471    /// 
472    /// # Errors
473    /// Returns error if decryption fails or data is corrupted
474    pub fn decrypt_profile(&self, key: &[u8]) -> Result<UserProfile> {
475        // Decrypt the profile data
476        let decrypted_data = Self::decrypt_profile_data(&self.encrypted_data, key)?;
477        
478        // Deserialize the profile
479        let profile: UserProfile = serde_json::from_slice(&decrypted_data)
480            .map_err(|e| P2PError::Serialization(e))?;
481        
482        Ok(profile)
483    }
484    
485    /// Retrieve access grant for a specific user
486    /// 
487    /// Looks up any existing access grants that have been issued to
488    /// the specified user ID for accessing this profile.
489    /// 
490    /// # Arguments
491    /// * `_user_id` - User ID to check for existing grants
492    /// 
493    /// # Returns
494    /// Access grant if one exists, None otherwise
495    pub fn get_access_grant(&self, _user_id: &str) -> Option<AccessGrant> {
496        // TODO: Implement access grant retrieval
497        None
498    }
499    
500    /// Validate an access grant for time and signature validity
501    /// 
502    /// Checks if an access grant is still valid by verifying it hasn't
503    /// expired and has a valid cryptographic signature.
504    /// 
505    /// # Arguments
506    /// * `_grant` - Access grant to validate
507    /// 
508    /// # Returns
509    /// True if grant is valid and not expired
510    pub fn is_grant_valid(_grant: &AccessGrant) -> bool {
511        // TODO: Implement grant validation
512        true
513    }
514    
515    /// Grant profile access permissions to another user
516    /// 
517    /// Creates an encrypted access grant allowing another user to access
518    /// specific parts of this profile based on the specified permissions.
519    /// 
520    /// # Arguments
521    /// * `user_id` - User ID to grant access to
522    /// * `public_key_bytes` - Public key of the user for encryption
523    /// * `permissions` - Specific permissions to grant
524    /// * `profile_key` - Profile encryption key for re-encryption
525    /// * `keypair` - Keypair for signing the access grant
526    /// 
527    /// # Returns
528    /// Success or error if grant creation fails
529    /// 
530    /// # Errors
531    /// Returns error if encryption or signing fails
532    pub fn grant_access(
533        &mut self, 
534        user_id: &str, 
535        public_key_bytes: &[u8],
536        permissions: ProfilePermissions,
537        profile_key: &[u8; 32],
538        keypair: &Keypair,
539    ) -> Result<()> {
540        // TODO: Implement proper access granting with encryption
541        // For now, just log the operation
542        info!("Granting access to user {} with permissions: {:?}", user_id, permissions);
543        Ok(())
544    }
545    
546    /// Revoke previously granted access from a user
547    /// 
548    /// Removes any existing access grants for the specified user,
549    /// effectively blocking their access to this profile.
550    /// 
551    /// # Arguments
552    /// * `_user_id` - User ID to revoke access from
553    /// 
554    /// # Returns
555    /// Success or error if revocation fails
556    /// 
557    /// # Errors
558    /// Returns error if user doesn't exist or revocation fails
559    pub fn revoke_access(&mut self, _user_id: &str) -> Result<()> {
560        // TODO: Implement access revocation
561        Ok(())
562    }
563}
564
565/// Identity verification challenge for proof-of-ownership
566/// 
567/// Used in challenge-response protocols to verify that a user actually
568/// controls the private key associated with their claimed identity.
569/// Prevents impersonation and establishes secure communication channels.
570#[derive(Debug, Clone, Serialize, Deserialize)]
571pub struct IdentityChallenge {
572    /// Unique identifier for this specific challenge
573    pub challenge_id: String,
574    /// Random challenge data that must be signed by the private key
575    pub challenge_data: Vec<u8>,
576    /// Timestamp when challenge was created
577    pub created_at: SystemTime,
578    /// Timestamp when challenge expires
579    pub expires_at: SystemTime,
580    /// User ID of the party issuing the challenge
581    pub challenger_id: UserId,
582}
583
584impl IdentityChallenge {
585    /// Create new identity challenge with random data
586    /// 
587    /// Generates a new challenge with 32 bytes of random data that expires
588    /// in 1 hour. The challenge must be signed to prove identity ownership.
589    /// 
590    /// # Arguments
591    /// * `challenger_id` - User ID of the party issuing the challenge
592    /// 
593    /// # Returns
594    /// New challenge ready for identity verification
595    pub fn new(challenger_id: UserId) -> Self {
596        use std::time::Duration;
597        let now = SystemTime::now();
598        Self {
599            challenge_id: uuid::Uuid::new_v4().to_string(),
600            challenge_data: rand::random::<[u8; 32]>().to_vec(),
601            created_at: now,
602            expires_at: now + Duration::from_secs(3600), // 1 hour
603            challenger_id,
604        }
605    }
606    
607    /// Check if challenge is still within its validity period
608    /// 
609    /// Challenges expire after 1 hour to prevent replay attacks and
610    /// ensure freshness of authentication attempts.
611    /// 
612    /// # Returns
613    /// True if challenge hasn't expired
614    pub fn is_valid(&mut self) -> bool {
615        SystemTime::now() < self.expires_at
616    }
617    
618    /// Create cryptographic response to this challenge
619    /// 
620    /// Signs the challenge data with the provided keypair to prove
621    /// ownership of the corresponding private key.
622    /// 
623    /// # Arguments
624    /// * `_keypair` - Ed25519 keypair to sign the challenge with
625    /// 
626    /// # Returns
627    /// Signed challenge response for verification
628    pub fn create_response(&self, keypair: &ed25519_dalek::Keypair) -> ChallengeResponse {
629        let mut signed_data = self.challenge_id.as_bytes().to_vec();
630        signed_data.extend_from_slice(&self.challenge_data);
631        let signature = keypair.sign(&signed_data);
632
633        ChallengeResponse {
634            challenge_id: self.challenge_id.clone(),
635            signature: signature.to_bytes().to_vec(),
636            response_data: Vec::new(),
637        }
638    }
639}
640
641/// Contact request between users for establishing connections
642/// 
643/// Represents a request from one user to connect with another. Includes
644/// proof of identity, requested permissions, and optional message.
645/// Prevents spam through cryptographic proof requirements.
646#[derive(Debug, Clone, Serialize, Deserialize)]
647pub struct ContactRequest {
648    /// Unique identifier for this contact request
649    pub request_id: String,
650    /// User ID of the sender making the request
651    pub from_user_id: UserId,
652    /// User ID of the recipient of the request
653    pub to_user_id: UserId,
654    /// Optional personal message explaining the connection request
655    pub message: Option<String>,
656    /// Permissions the sender is requesting from the recipient
657    pub requested_permissions: ProfilePermissions,
658    /// Cryptographic proof of sender's identity
659    pub sender_proof: ChallengeResponse,
660    /// Timestamp when request was created
661    pub created_at: SystemTime,
662    /// Timestamp when request expires
663    pub expires_at: SystemTime,
664    /// Ed25519 signature of the request data
665    pub signature: Vec<u8>,
666    /// Current status of the request
667    pub status: ContactRequestStatus,
668}
669
670/// Status of a contact request throughout its lifecycle
671/// 
672/// Tracks the current state of a contact request from creation
673/// through resolution or expiration.
674#[derive(Debug, Clone, Serialize, Deserialize)]
675pub enum ContactRequestStatus {
676    /// Request has been sent but not yet responded to
677    Pending,
678    /// Request has been accepted by the recipient
679    Accepted,
680    /// Request has been rejected by the recipient
681    Rejected,
682    /// Request has expired without response
683    Expired,
684}
685
686/// Fine-grained profile permissions for privacy control
687/// 
688/// Defines what information and capabilities are available to other users.
689/// Enables granular privacy control and supports different relationship levels.
690#[derive(Debug, Clone, Serialize, Deserialize)]
691pub struct ProfilePermissions {
692    /// Whether profile is publicly visible to all users
693    pub public_profile: bool,
694    /// Whether user can be found through search and discovery
695    pub discoverable: bool,
696    /// Whether user accepts direct messages
697    pub allow_messages: bool,
698    /// Whether user accepts friend/contact requests
699    pub allow_friend_requests: bool,
700    /// Whether display name is visible
701    pub can_see_display_name: bool,
702    /// Whether avatar image is visible
703    pub can_see_avatar: bool,
704    /// Whether status message is visible
705    pub can_see_status: bool,
706    /// Whether contact information is visible
707    pub can_see_contact_info: bool,
708    /// Whether last seen timestamp is visible
709    pub can_see_last_seen: bool,
710    /// Whether custom fields are visible
711    pub can_see_custom_fields: bool,
712}
713
714impl Default for ProfilePermissions {
715    fn default() -> Self {
716        Self {
717            public_profile: false,
718            discoverable: true,
719            allow_messages: true,
720            allow_friend_requests: true,
721            can_see_display_name: true,
722            can_see_avatar: true,
723            can_see_status: true,
724            can_see_contact_info: false,
725            can_see_last_seen: false,
726            can_see_custom_fields: false,
727        }
728    }
729}
730
731/// Default permissions applied to new contacts
732/// 
733/// Defines the baseline permissions granted to users who successfully
734/// connect. Can be customized per-user after connection is established.
735#[derive(Debug, Clone, Serialize, Deserialize)]
736pub struct DefaultPermissions {
737    /// Whether contacts can see the user's display name
738    pub can_see_display_name: bool,
739    /// Whether contacts can see the user's avatar
740    pub can_see_avatar: bool,
741    /// Whether contacts can see the user's status message
742    pub can_see_status: bool,
743    /// Whether contacts can see contact information
744    pub can_see_contact_info: bool,
745    /// Whether contacts can see last seen timestamp
746    pub can_see_last_seen: bool,
747    /// Whether contacts can see custom fields
748    pub can_see_custom_fields: bool,
749}
750
751impl Default for DefaultPermissions {
752    fn default() -> Self {
753        Self {
754            can_see_display_name: true,
755            can_see_avatar: true,
756            can_see_status: true,
757            can_see_contact_info: false,
758            can_see_last_seen: false,
759            can_see_custom_fields: false,
760        }
761    }
762}
763
764/// Privacy settings for user profiles and communications
765/// 
766/// Controls how much information is shared with other users and
767/// configures security features like encryption and key rotation.
768#[derive(Debug, Clone, Serialize, Deserialize)]
769pub struct PrivacySettings {
770    /// Whether to show online/offline status to others
771    pub show_online_status: bool,
772    /// Whether to show last seen timestamp to others
773    pub show_last_seen: bool,
774    /// Whether to allow others to view profile information
775    pub allow_profile_view: bool,
776    /// Whether to require end-to-end encryption for messaging
777    pub encrypted_messaging: bool,
778    /// Whether to require proof of humanity for contact requests
779    pub require_proof_of_humanity: bool,
780    /// Maximum age for accepting contact requests
781    pub max_contact_request_age: std::time::Duration,
782    /// Whether to enable forward secrecy for communications
783    pub enable_forward_secrecy: bool,
784    /// Whether to automatically rotate encryption keys
785    pub auto_rotate_keys: bool,
786    /// Interval between automatic key rotations
787    pub key_rotation_interval: std::time::Duration,
788}
789
790impl Default for PrivacySettings {
791    fn default() -> Self {
792        Self {
793            show_online_status: true,
794            show_last_seen: true,
795            allow_profile_view: true,
796            encrypted_messaging: false,
797            require_proof_of_humanity: false,
798            max_contact_request_age: std::time::Duration::from_secs(86400 * 30), // 30 days
799            enable_forward_secrecy: true,
800            auto_rotate_keys: true,
801            key_rotation_interval: std::time::Duration::from_secs(86400 * 90), // 90 days
802        }
803    }
804}
805
806/// Settings controlling how users can find and contact this profile
807/// 
808/// Manages discoverability through various channels while maintaining
809/// privacy and preventing unwanted contact.
810#[derive(Debug, Clone, Serialize, Deserialize)]
811pub struct DiscoverabilitySettings {
812    /// Whether user can be found by searching display name
813    pub discoverable_by_name: bool,
814    /// Whether friends can recommend this user to others
815    pub discoverable_by_friends: bool,
816    /// Whether to accept contact requests from unknown users
817    pub allow_contact_requests: bool,
818    /// Whether to require mutual friends for contact requests
819    pub require_mutual_friends: bool,
820    /// Whether to appear in public user directories
821    pub listed_in_directory: bool,
822}
823
824impl Default for DiscoverabilitySettings {
825    fn default() -> Self {
826        Self {
827            discoverable_by_name: true,
828            discoverable_by_friends: true,
829            allow_contact_requests: true,
830            require_mutual_friends: false,
831            listed_in_directory: false,
832        }
833    }
834}
835
836/// Comprehensive user preferences for behavior and appearance
837/// 
838/// Aggregates all user preference settings including UI preferences,
839/// privacy controls, and default permission settings.
840#[derive(Debug, Clone, Serialize, Deserialize)]
841pub struct UserPreferences {
842    /// UI theme preference ("light", "dark", etc.)
843    pub theme: String,
844    /// Language preference as ISO 639-1 code
845    pub language: String,
846    /// Whether to show notifications for events
847    pub notifications_enabled: bool,
848    /// Whether to automatically accept friend requests
849    pub auto_accept_friends: bool,
850    /// Settings for how user can be discovered
851    pub discovery: DiscoverabilitySettings,
852    /// Privacy and security settings
853    pub privacy: PrivacySettings,
854    /// Default permissions for new contacts
855    pub default_permissions: DefaultPermissions,
856}
857
858impl Default for UserPreferences {
859    fn default() -> Self {
860        Self {
861            theme: "dark".to_string(),
862            language: "en".to_string(),
863            notifications_enabled: true,
864            auto_accept_friends: false,
865            discovery: DiscoverabilitySettings::default(),
866            privacy: PrivacySettings::default(),
867            default_permissions: DefaultPermissions::default(),
868        }
869    }
870}
871
872/// Identity verification level indicating trust and authenticity
873/// 
874/// Higher levels provide stronger guarantees about identity authenticity
875/// and are used for reputation and trust calculations.
876#[derive(Debug, Clone, Serialize, Deserialize)]
877pub enum VerificationLevel {
878    /// No verification performed
879    Unverified,
880    /// Self-signed cryptographic identity only
881    SelfSigned,
882    /// Email address has been verified
883    EmailVerified,
884    /// Phone number has been verified
885    PhoneVerified,
886    /// Identity verified through network consensus
887    NetworkVerified,
888    /// Maximum verification through multiple channels
889    FullyVerified,
890}
891
892/// Cryptographic proof of successful challenge response
893/// 
894/// Contains the signed response to an identity challenge, proving
895/// ownership of a private key without revealing it.
896#[derive(Debug, Clone, Serialize, Deserialize)]
897pub struct ChallengeProof {
898    /// ID of the challenge this proof responds to
899    pub challenge_id: String,
900    /// Additional proof data specific to challenge type
901    pub proof_data: Vec<u8>,
902    /// Ed25519 signature of the challenge data
903    pub signature: Vec<u8>,
904    /// Public key used for signature verification
905    pub public_key: Vec<u8>,
906    /// Timestamp when proof was created
907    pub timestamp: SystemTime,
908}
909
910impl ChallengeProof {
911    /// Verify this proof against a challenge and public key
912    /// 
913    /// Validates that the proof correctly responds to the challenge
914    /// and was signed by the claimed public key.
915    /// 
916    /// # Arguments
917    /// * `challenge` - Original challenge to verify against
918    /// * `public_key_bytes` - Expected public key for verification
919    /// 
920    /// # Returns
921    /// True if proof is valid, false otherwise
922    /// 
923    /// # Errors
924    /// Returns error if cryptographic verification fails
925    pub fn verify(&self, challenge: &IdentityChallenge, public_key_bytes: &[u8]) -> Result<bool> {
926        // Check if challenge IDs match
927        if self.challenge_id != challenge.challenge_id {
928            return Ok(false);
929        }
930        
931        // Check if public keys match
932        if self.public_key != public_key_bytes {
933            return Ok(false);
934        }
935        
936        // Check if challenge is still valid
937        if SystemTime::now() > challenge.expires_at {
938            return Ok(false);
939        }
940        
941        // Verify the signature of the challenge data
942        use ed25519_dalek::{PublicKey, Signature, Verifier};
943        
944        // Parse the public key
945        let public_key = PublicKey::from_bytes(&self.public_key)
946            .map_err(|e| P2PError::Identity(format!("Invalid public key in proof: {}", e)))?;
947        
948        // Parse the signature
949        let signature = Signature::from_bytes(&self.signature)
950            .map_err(|e| P2PError::Identity(format!("Invalid signature in proof: {}", e)))?;
951        
952        // Create the signed data: challenge_id + proof_data
953        let mut signed_data = challenge.challenge_id.as_bytes().to_vec();
954        signed_data.extend_from_slice(&self.proof_data);
955        
956        // Verify signature
957        match public_key.verify(&signed_data, &signature) {
958            Ok(()) => Ok(true),
959            Err(_) => Ok(false),
960        }
961    }
962}
963
964/// Identity manager for handling user identities and network integration
965pub struct IdentityManager {
966    /// Configuration for the identity manager
967    config: IdentityManagerConfig,
968}
969
970/// Identity manager configuration
971#[derive(Debug, Clone, Serialize, Deserialize)]
972pub struct IdentityManagerConfig {
973    /// Cache TTL for identities and profiles
974    pub cache_ttl: std::time::Duration,
975    /// Challenge timeout duration
976    pub challenge_timeout: std::time::Duration,
977}
978
979impl Default for IdentityManagerConfig {
980    fn default() -> Self {
981        Self {
982            cache_ttl: std::time::Duration::from_secs(3600), // 1 hour
983            challenge_timeout: std::time::Duration::from_secs(300), // 5 minutes
984        }
985    }
986}
987
988impl IdentityManager {
989    /// Create a new identity manager
990    pub fn new(config: IdentityManagerConfig) -> Self {
991        Self { config }
992    }
993    
994    /// Create a new user identity
995    pub async fn create_identity(
996        &self,
997        display_name: String,
998        three_word_address: String,
999        _ipv6_identity: Option<IPv6NodeID>,
1000        _ipv6_keypair: Option<&Keypair>,
1001    ) -> Result<UserIdentity> {
1002        let (identity, _keypair) = UserIdentity::new(display_name, three_word_address)?;
1003        Ok(identity)
1004    }
1005    
1006    /// Export identity for backup
1007    pub async fn export_identity(&self, _user_id: &str) -> Result<Vec<u8>> {
1008        // TODO: Implement identity export
1009        Ok(vec![])
1010    }
1011    
1012    /// Import identity from backup
1013    pub async fn import_identity(&self, _data: &[u8], _password: &str) -> Result<UserIdentity> {
1014        // TODO: Implement identity import
1015        UserIdentity::new("Imported User".to_string(), "imported.user.test".to_string()).map(|(identity, _)| identity)
1016    }
1017    
1018    /// Create challenge for identity verification
1019    pub async fn create_challenge(&self, duration: std::time::Duration) -> IdentityChallenge {
1020        let now = SystemTime::now();
1021        IdentityChallenge {
1022            challenge_id: uuid::Uuid::new_v4().to_string(),
1023            challenge_data: rand::random::<[u8; 32]>().to_vec(),
1024            created_at: now,
1025            expires_at: now + duration,
1026            challenger_id: "system".to_string(),
1027        }
1028    }
1029    
1030    /// Verify challenge response
1031    pub async fn verify_challenge_response(&self, _proof: &ChallengeProof, _public_key: &[u8]) -> Result<bool> {
1032        // TODO: Implement proper verification
1033        Ok(true)
1034    }
1035}
1036
1037#[cfg(test)]
1038mod tests {
1039    use super::*;
1040    use std::time::Duration;
1041
1042    #[tokio::test]
1043    async fn test_identity_creation() {
1044        let config = IdentityManagerConfig::default();
1045        let manager = IdentityManager::new(config);
1046        
1047        let identity = manager.create_identity(
1048            "Test User".to_string(),
1049            "forest.lightning.compass".to_string(),
1050            None,
1051            None,
1052        ).await.unwrap();
1053        
1054        assert_eq!(identity.display_name_hint, "Test User");
1055        assert_eq!(identity.three_word_address, "forest.lightning.compass");
1056        assert!(!identity.public_key.is_empty());
1057    }
1058    
1059    #[tokio::test]
1060    async fn test_identity_import_export() {
1061        let config = IdentityManagerConfig::default();
1062        let manager = IdentityManager::new(config);
1063        
1064        // Create identity
1065        let original_identity = manager.create_identity(
1066            "Test User".to_string(),
1067            "ocean.thunder.falcon".to_string(),
1068            None,
1069            None,
1070        ).await.unwrap();
1071        
1072        // Export identity
1073        let exported_data = manager.export_identity(&original_identity.user_id).await.unwrap();
1074        
1075        // Import identity
1076        let imported_identity = manager.import_identity(&exported_data, "password123").await.unwrap();
1077        
1078        // Verify identities match
1079        assert_eq!(original_identity.user_id, imported_identity.user_id);
1080        assert_eq!(original_identity.public_key, imported_identity.public_key);
1081        assert_eq!(original_identity.display_name_hint, imported_identity.display_name_hint);
1082    }
1083    
1084    #[tokio::test]
1085    async fn test_challenge_system() {
1086        let config = IdentityManagerConfig::default();
1087        let manager = IdentityManager::new(config);
1088        
1089        let identity = manager.create_identity(
1090            "Test User".to_string(),
1091            "test.user.example".to_string(),
1092            None,
1093            None,
1094        ).await.unwrap();
1095        
1096        // Create challenge
1097        let challenge = manager.create_challenge(Duration::from_secs(300)).await;
1098        
1099        // Create proof for challenge  
1100        let proof = ChallengeProof {
1101            challenge_id: challenge.challenge_id.clone(),
1102            proof_data: challenge.challenge_data.clone(),
1103            signature: vec![0; 64], // Placeholder signature
1104            public_key: identity.public_key.clone(),
1105            timestamp: SystemTime::now(),
1106        };
1107        
1108        // Verify response
1109        let is_valid = manager.verify_challenge_response(&proof, &identity.public_key).await.unwrap();
1110        assert!(is_valid);
1111    }
1112}