saorsa_core/adaptive/
identity.rs1use super::*;
20use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
21use serde::{Deserialize, Serialize};
22use sha2::{Digest, Sha256};
23use std::time::{SystemTime, UNIX_EPOCH};
24
25#[derive(Clone)]
27pub struct NodeIdentity {
28 signing_key: SigningKey,
30 node_id: NodeId,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct SignedMessage<T: Serialize> {
37 pub payload: T,
39 pub sender_id: NodeId,
41 pub timestamp: u64,
43 pub signature: Vec<u8>,
45}
46
47impl NodeIdentity {
48 pub fn generate() -> Result<Self> {
50 let mut csprng = rand::thread_rng();
51 let signing_key = SigningKey::generate(&mut csprng);
52
53 let node_id = Self::compute_node_id(&signing_key.verifying_key());
54
55 Ok(Self {
56 signing_key,
57 node_id,
58 })
59 }
60
61 pub fn from_signing_key(signing_key: SigningKey) -> Result<Self> {
63 let node_id = Self::compute_node_id(&signing_key.verifying_key());
64
65 Ok(Self {
66 signing_key,
67 node_id,
68 })
69 }
70
71 pub fn compute_node_id(public_key: &VerifyingKey) -> NodeId {
73 let mut hasher = Sha256::new();
74 hasher.update(public_key.as_bytes());
75 let result = hasher.finalize();
76
77 let mut bytes = [0u8; 32];
79 bytes.copy_from_slice(&result);
80 crate::peer_record::UserId::from_bytes(bytes)
81 }
82
83 pub fn sign_message<T: Serialize + Clone>(&self, message: &T) -> Result<SignedMessage<T>> {
85 let timestamp = SystemTime::now()
86 .duration_since(UNIX_EPOCH)
87 .map_err(|e| AdaptiveNetworkError::Other(e.to_string()))?
88 .as_secs();
89
90 let payload_bytes =
91 bincode::serialize(message).map_err(AdaptiveNetworkError::Serialization)?;
92
93 let mut bytes_to_sign = Vec::new();
95 bytes_to_sign.extend_from_slice(&payload_bytes);
96 bytes_to_sign.extend_from_slice(&self.node_id.hash);
97 bytes_to_sign.extend_from_slice(×tamp.to_le_bytes());
98
99 let signature = self.signing_key.sign(&bytes_to_sign);
100
101 Ok(SignedMessage {
102 payload: message.clone(),
103 sender_id: self.node_id.clone(),
104 timestamp,
105 signature: signature.to_bytes().to_vec(),
106 })
107 }
108
109 pub fn node_id(&self) -> &NodeId {
111 &self.node_id
112 }
113
114 pub fn public_key(&self) -> VerifyingKey {
116 self.signing_key.verifying_key()
117 }
118}
119
120impl<T: Serialize + for<'de> Deserialize<'de>> SignedMessage<T> {
121 pub fn verify(&self, public_key: &VerifyingKey) -> Result<bool> {
123 let payload_bytes =
124 bincode::serialize(&self.payload).map_err(AdaptiveNetworkError::Serialization)?;
125
126 let mut bytes_to_verify = Vec::new();
128 bytes_to_verify.extend_from_slice(&payload_bytes);
129 bytes_to_verify.extend_from_slice(&self.sender_id.hash);
130 bytes_to_verify.extend_from_slice(&self.timestamp.to_le_bytes());
131
132 let signature_bytes: [u8; 64] = self
133 .signature
134 .as_slice()
135 .try_into()
136 .map_err(|_| AdaptiveNetworkError::Other("Invalid signature length".to_string()))?;
137 let signature = Signature::from_bytes(&signature_bytes);
138
139 Ok(public_key.verify(&bytes_to_verify, &signature).is_ok())
140 }
141
142 pub fn age(&self) -> Result<u64> {
144 let now = SystemTime::now()
145 .duration_since(UNIX_EPOCH)
146 .map_err(|e| AdaptiveNetworkError::Other(e.to_string()))?
147 .as_secs();
148
149 Ok(now.saturating_sub(self.timestamp))
150 }
151}
152
153#[derive(Debug, Serialize, Deserialize)]
155pub struct StoredIdentity {
156 pub secret_key: Vec<u8>,
158 pub public_key: Vec<u8>,
160 pub node_id: NodeId,
162}
163
164impl StoredIdentity {
165 pub fn from_identity(identity: &NodeIdentity) -> Self {
167 Self {
168 secret_key: identity.signing_key.to_bytes().to_vec(),
169 public_key: identity.signing_key.verifying_key().to_bytes().to_vec(),
170 node_id: identity.node_id.clone(),
171 }
172 }
173
174 pub fn to_identity(&self) -> Result<NodeIdentity> {
176 let secret_key_bytes: [u8; 32] =
177 self.secret_key.as_slice().try_into().map_err(|_| {
178 AdaptiveNetworkError::Other("Invalid secret key length".to_string())
179 })?;
180 let signing_key = SigningKey::from_bytes(&secret_key_bytes);
181
182 let public_key_bytes: [u8; 32] =
183 self.public_key.as_slice().try_into().map_err(|_| {
184 AdaptiveNetworkError::Other("Invalid public key length".to_string())
185 })?;
186 let public_key = VerifyingKey::from_bytes(&public_key_bytes)
187 .map_err(|e| AdaptiveNetworkError::Other(format!("Invalid public key: {e}")))?;
188
189 if signing_key.verifying_key().to_bytes() != public_key.to_bytes() {
191 return Err(AdaptiveNetworkError::Other(
192 "Public key doesn't match signing key".to_string(),
193 ));
194 }
195
196 let computed_id = NodeIdentity::compute_node_id(&public_key);
198 if computed_id != self.node_id {
199 return Err(AdaptiveNetworkError::Other(
200 "Stored node ID doesn't match computed ID".to_string(),
201 ));
202 }
203
204 Ok(NodeIdentity {
205 signing_key,
206 node_id: self.node_id.clone(),
207 })
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214 use rand_core::RngCore;
215
216 #[test]
217 fn test_identity_generation() {
218 let identity = NodeIdentity::generate().unwrap();
219
220 let computed_id = NodeIdentity::compute_node_id(&identity.public_key());
222 assert_eq!(&computed_id, identity.node_id());
223
224 }
226
227 #[test]
228 fn test_message_signing_and_verification() {
229 let identity = NodeIdentity::generate().unwrap();
230
231 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
232 struct TestMessage {
233 content: String,
234 value: u64,
235 }
236
237 let message = TestMessage {
238 content: "Hello, P2P!".to_string(),
239 value: 42,
240 };
241
242 let signed = identity.sign_message(&message).unwrap();
244
245 assert!(signed.verify(&identity.public_key()).unwrap());
247
248 let other_identity = NodeIdentity::generate().unwrap();
250 assert!(!signed.verify(&other_identity.public_key()).unwrap());
251 }
252
253 #[test]
254 fn test_proof_of_work_verification() {}
255
256 #[test]
257 fn test_identity_serialization() {
258 let identity = NodeIdentity::generate().unwrap();
259
260 let stored = StoredIdentity::from_identity(&identity);
262
263 let restored = stored.to_identity().unwrap();
265
266 assert_eq!(identity.node_id(), restored.node_id());
268 assert_eq!(
269 identity.public_key().to_bytes(),
270 restored.public_key().to_bytes()
271 );
272 }
273}