identity.rs
1 //! Identity Types 2 //! 3 //! Strict newtype wrappers for Machine and User identities. 4 //! The compiler enforces separation - you cannot accidentally use 5 //! a MachineIdentity where a UserIdentity is expected. 6 //! 7 //! # Architecture 8 //! 9 //! - **MachineIdentity**: Infrastructure operations (routing, DHT, mesh address) 10 //! - **UserIdentity**: Application operations (messaging, content signing, mailbox) 11 12 use ed25519_dalek::{SigningKey, VerifyingKey, Signature, Signer}; 13 14 /// Machine identity for infrastructure operations. 15 /// 16 /// Used for: 17 /// - Mesh address derivation 18 /// - Routing table operations 19 /// - DHT participation (FindNode, Ping) 20 /// - Transport layer authentication 21 /// 22 /// This identity is tied to the node/device, not the user. 23 #[derive(Debug)] 24 pub struct MachineIdentity(SigningKey); 25 26 impl MachineIdentity { 27 /// Create a new machine identity from a signing key 28 pub fn new(key: SigningKey) -> Self { 29 Self(key) 30 } 31 32 /// Generate a new random machine identity 33 pub fn generate() -> Self { 34 Self(SigningKey::generate(&mut rand::rngs::OsRng)) 35 } 36 37 /// Get the verifying (public) key 38 pub fn verifying_key(&self) -> VerifyingKey { 39 self.0.verifying_key() 40 } 41 42 /// Get the public key bytes (32 bytes) 43 pub fn public_bytes(&self) -> [u8; 32] { 44 *self.0.verifying_key().as_bytes() 45 } 46 47 /// Sign data for infrastructure operations 48 pub fn sign(&self, data: &[u8]) -> Signature { 49 self.0.sign(data) 50 } 51 52 /// Expose the raw signing key. 53 /// 54 /// # Security 55 /// This method exposes private key material. Only use for: 56 /// - Serialization to secure storage 57 /// - Key derivation in trusted contexts 58 /// 59 /// Never log, transmit, or store the result in plaintext. 60 pub fn expose_signing_key(&self) -> &SigningKey { 61 &self.0 62 } 63 64 /// Create from raw bytes (for deserialization) 65 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, ed25519_dalek::SignatureError> { 66 Ok(Self(SigningKey::from_bytes(bytes))) 67 } 68 } 69 70 /// User identity for application operations. 71 /// 72 /// Used for: 73 /// - Message signing and encryption 74 /// - Content ownership signatures 75 /// - Mailbox address derivation 76 /// - Contact relationships 77 /// 78 /// This identity represents a user/account and is portable between nodes. 79 #[derive(Debug)] 80 pub struct UserIdentity(SigningKey); 81 82 impl UserIdentity { 83 /// Create a new user identity from a signing key 84 pub fn new(key: SigningKey) -> Self { 85 Self(key) 86 } 87 88 /// Generate a new random user identity 89 pub fn generate() -> Self { 90 Self(SigningKey::generate(&mut rand::rngs::OsRng)) 91 } 92 93 /// Get the verifying (public) key 94 pub fn verifying_key(&self) -> VerifyingKey { 95 self.0.verifying_key() 96 } 97 98 /// Get the public key bytes (32 bytes) 99 pub fn public_bytes(&self) -> [u8; 32] { 100 *self.0.verifying_key().as_bytes() 101 } 102 103 /// Sign data for user operations (messages, content) 104 pub fn sign(&self, data: &[u8]) -> Signature { 105 self.0.sign(data) 106 } 107 108 /// Expose the raw signing key. 109 /// 110 /// # Security 111 /// This method exposes private key material. Only use for: 112 /// - Serialization to secure storage 113 /// - Key derivation in trusted contexts 114 /// 115 /// Never log, transmit, or store the result in plaintext. 116 pub fn expose_signing_key(&self) -> &SigningKey { 117 &self.0 118 } 119 120 /// Create from raw bytes (for deserialization) 121 pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, ed25519_dalek::SignatureError> { 122 Ok(Self(SigningKey::from_bytes(bytes))) 123 } 124 } 125 126 #[cfg(test)] 127 mod tests { 128 use super::*; 129 130 #[test] 131 fn machine_identity_roundtrip() { 132 let machine = MachineIdentity::generate(); 133 let pubkey = machine.public_bytes(); 134 135 // Sign and verify 136 let data = b"routing data"; 137 let sig = machine.sign(data); 138 assert!(machine.verifying_key().verify_strict(data, &sig).is_ok()); 139 140 // Roundtrip through bytes 141 let bytes = machine.expose_signing_key().to_bytes(); 142 let restored = MachineIdentity::from_bytes(&bytes).unwrap(); 143 assert_eq!(restored.public_bytes(), pubkey); 144 } 145 146 #[test] 147 fn user_identity_roundtrip() { 148 let user = UserIdentity::generate(); 149 let pubkey = user.public_bytes(); 150 151 // Sign and verify 152 let data = b"message content"; 153 let sig = user.sign(data); 154 assert!(user.verifying_key().verify_strict(data, &sig).is_ok()); 155 156 // Roundtrip through bytes 157 let bytes = user.expose_signing_key().to_bytes(); 158 let restored = UserIdentity::from_bytes(&bytes).unwrap(); 159 assert_eq!(restored.public_bytes(), pubkey); 160 } 161 162 #[test] 163 fn identities_are_distinct_types() { 164 // This test ensures the compiler enforces type separation. 165 // If you uncomment the line below, it will fail to compile: 166 // let machine: MachineIdentity = UserIdentity::generate(); // ERROR! 167 168 let machine = MachineIdentity::generate(); 169 let user = UserIdentity::generate(); 170 171 // Different types, different keys 172 assert_ne!(machine.public_bytes(), user.public_bytes()); 173 } 174 }