1use crate::zeroizing::SecureBuffer;
36use blake3::Hasher;
37use chacha20poly1305::{ChaCha20Poly1305, KeyInit, aead::Aead};
38use curve25519_dalek::{RistrettoPoint, Scalar, constants::RISTRETTO_BASEPOINT_POINT};
39use rand::RngCore;
40use serde::{Deserialize, Serialize};
41use std::fmt;
42use zeroize::{Zeroize, ZeroizeOnDrop};
43
44pub type IbeResult<T> = Result<T, IbeError>;
46
47#[derive(Debug, Clone, PartialEq, Eq)]
49pub enum IbeError {
50 InvalidIdentity,
52 DecryptionFailed,
54 SerializationFailed,
56 DeserializationFailed,
58 InvalidCiphertext,
60}
61
62impl fmt::Display for IbeError {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 IbeError::InvalidIdentity => write!(f, "Invalid identity string"),
66 IbeError::DecryptionFailed => write!(f, "Decryption failed"),
67 IbeError::SerializationFailed => write!(f, "Serialization failed"),
68 IbeError::DeserializationFailed => write!(f, "Deserialization failed"),
69 IbeError::InvalidCiphertext => write!(f, "Invalid ciphertext"),
70 }
71 }
72}
73
74impl std::error::Error for IbeError {}
75
76#[derive(Clone, Zeroize, ZeroizeOnDrop)]
80pub struct IbeMasterKey {
81 #[zeroize(skip)]
83 master_secret: Scalar,
84}
85
86#[derive(Clone, Debug, Serialize, Deserialize)]
90pub struct IbeParams {
91 #[serde(with = "serde_ristretto_point")]
93 master_public: RistrettoPoint,
94}
95
96pub struct IbeMaster {
100 master_key: IbeMasterKey,
102 params: IbeParams,
104}
105
106#[derive(Clone, Zeroize, ZeroizeOnDrop)]
110pub struct IbeSecretKey {
111 identity: String,
113 #[zeroize(skip)]
115 secret: Scalar,
116 #[zeroize(skip)]
118 params: IbeParams,
119}
120
121#[derive(Clone, Serialize, Deserialize)]
123pub struct IbeCiphertext {
124 #[serde(with = "serde_ristretto_point")]
126 ephemeral: RistrettoPoint,
127 ciphertext: Vec<u8>,
129 nonce: [u8; 12],
131}
132
133impl IbeMaster {
134 pub fn generate() -> Self {
136 let mut rng = rand::thread_rng();
137 let mut master_secret_bytes = [0u8; 32];
138 rng.fill_bytes(&mut master_secret_bytes);
139 let master_secret = Scalar::from_bytes_mod_order(master_secret_bytes);
140 let master_public = master_secret * RISTRETTO_BASEPOINT_POINT;
141
142 let master_key = IbeMasterKey { master_secret };
143 let params = IbeParams { master_public };
144
145 Self { master_key, params }
146 }
147
148 pub fn public_params(&self) -> IbeParams {
150 self.params.clone()
151 }
152
153 pub fn extract_secret_key(&self, identity: &str) -> IbeSecretKey {
157 let identity_hash = hash_identity_to_scalar(identity);
159
160 let secret = self.master_key.master_secret * identity_hash;
162
163 IbeSecretKey {
164 identity: identity.to_string(),
165 secret,
166 params: self.params.clone(),
167 }
168 }
169
170 pub fn master_key(&self) -> &IbeMasterKey {
172 &self.master_key
173 }
174}
175
176impl IbeParams {
177 pub fn encrypt(&self, identity: &str, plaintext: &[u8]) -> IbeResult<IbeCiphertext> {
179 let mut rng = rand::thread_rng();
180
181 let mut ephemeral_secret_bytes = [0u8; 32];
183 rng.fill_bytes(&mut ephemeral_secret_bytes);
184 let ephemeral_secret = Scalar::from_bytes_mod_order(ephemeral_secret_bytes);
185 let ephemeral = ephemeral_secret * RISTRETTO_BASEPOINT_POINT;
186
187 let identity_hash = hash_identity_to_scalar(identity);
189 let identity_point = identity_hash * self.master_public;
190
191 let shared_point = ephemeral_secret * identity_point;
193
194 let encryption_key = derive_encryption_key(&shared_point);
196
197 let cipher = ChaCha20Poly1305::new(&encryption_key.into());
199 let mut nonce_bytes = [0u8; 12];
200 rng.fill_bytes(&mut nonce_bytes);
201 let nonce = chacha20poly1305::Nonce::from(nonce_bytes);
202
203 let ciphertext = cipher
204 .encrypt(&nonce, plaintext)
205 .map_err(|_| IbeError::DecryptionFailed)?;
206
207 Ok(IbeCiphertext {
208 ephemeral,
209 ciphertext,
210 nonce: nonce_bytes,
211 })
212 }
213}
214
215impl IbeSecretKey {
216 pub fn decrypt(&self, ciphertext: &IbeCiphertext) -> IbeResult<SecureBuffer> {
218 let shared_point = self.secret * ciphertext.ephemeral;
220
221 let decryption_key = derive_encryption_key(&shared_point);
223
224 let cipher = ChaCha20Poly1305::new(&decryption_key.into());
226 let nonce = chacha20poly1305::Nonce::from(ciphertext.nonce);
227
228 let plaintext = cipher
229 .decrypt(&nonce, ciphertext.ciphertext.as_ref())
230 .map_err(|_| IbeError::DecryptionFailed)?;
231
232 Ok(SecureBuffer::from(plaintext))
233 }
234
235 pub fn identity(&self) -> &str {
237 &self.identity
238 }
239
240 pub fn to_bytes(&self) -> Vec<u8> {
242 crate::codec::encode(&(&self.identity, self.secret.to_bytes(), &self.params))
243 .unwrap_or_default()
244 }
245
246 pub fn from_bytes(bytes: &[u8]) -> IbeResult<Self> {
248 let (identity, secret_bytes, params): (String, [u8; 32], IbeParams) =
249 crate::codec::decode(bytes).map_err(|_| IbeError::DeserializationFailed)?;
250
251 let secret = Scalar::from_bytes_mod_order(secret_bytes);
252
253 Ok(Self {
254 identity,
255 secret,
256 params,
257 })
258 }
259}
260
261impl IbeCiphertext {
262 pub fn to_bytes(&self) -> Vec<u8> {
264 crate::codec::encode(self).unwrap_or_default()
265 }
266
267 pub fn from_bytes(bytes: &[u8]) -> IbeResult<Self> {
269 crate::codec::decode(bytes).map_err(|_| IbeError::DeserializationFailed)
270 }
271}
272
273fn hash_identity_to_scalar(identity: &str) -> Scalar {
275 let mut hasher = Hasher::new();
276 hasher.update(b"IBE-Identity-Hash:");
277 hasher.update(identity.as_bytes());
278 let hash = hasher.finalize();
279
280 let mut scalar_bytes = [0u8; 32];
282 scalar_bytes.copy_from_slice(&hash.as_bytes()[..32]);
283
284 Scalar::from_bytes_mod_order(scalar_bytes)
285}
286
287fn derive_encryption_key(point: &RistrettoPoint) -> [u8; 32] {
289 let point_bytes = point.compress().to_bytes();
290
291 let mut hasher = Hasher::new();
292 hasher.update(b"IBE-Key-Derivation:");
293 hasher.update(&point_bytes);
294 let hash = hasher.finalize();
295
296 let mut key = [0u8; 32];
297 key.copy_from_slice(&hash.as_bytes()[..32]);
298 key
299}
300
301mod serde_ristretto_point {
303 use curve25519_dalek::RistrettoPoint;
304 use serde::{Deserialize, Deserializer, Serialize, Serializer};
305
306 pub fn serialize<S>(point: &RistrettoPoint, serializer: S) -> Result<S::Ok, S::Error>
307 where
308 S: Serializer,
309 {
310 point.compress().to_bytes().serialize(serializer)
311 }
312
313 pub fn deserialize<'de, D>(deserializer: D) -> Result<RistrettoPoint, D::Error>
314 where
315 D: Deserializer<'de>,
316 {
317 let bytes: [u8; 32] = Deserialize::deserialize(deserializer)?;
318 let compressed = curve25519_dalek::ristretto::CompressedRistretto(bytes);
319 compressed
320 .decompress()
321 .ok_or_else(|| serde::de::Error::custom("Invalid RistrettoPoint"))
322 }
323}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328
329 #[test]
330 fn test_ibe_basic() {
331 let master = IbeMaster::generate();
332 let params = master.public_params();
333
334 let alice_id = "alice@example.com";
335 let alice_sk = master.extract_secret_key(alice_id);
336
337 let plaintext = b"Secret message for Alice";
338 let ciphertext = params.encrypt(alice_id, plaintext).unwrap();
339
340 let decrypted = alice_sk.decrypt(&ciphertext).unwrap();
341 assert_eq!(plaintext.as_slice(), decrypted.as_bytes());
342 }
343
344 #[test]
345 fn test_ibe_multiple_users() {
346 let master = IbeMaster::generate();
347 let params = master.public_params();
348
349 let alice_sk = master.extract_secret_key("alice@example.com");
350 let bob_sk = master.extract_secret_key("bob@example.com");
351
352 let msg_for_alice = b"Message for Alice";
353 let msg_for_bob = b"Message for Bob";
354
355 let ct_alice = params.encrypt("alice@example.com", msg_for_alice).unwrap();
356 let ct_bob = params.encrypt("bob@example.com", msg_for_bob).unwrap();
357
358 let dec_alice = alice_sk.decrypt(&ct_alice).unwrap();
359 let dec_bob = bob_sk.decrypt(&ct_bob).unwrap();
360
361 assert_eq!(msg_for_alice.as_slice(), dec_alice.as_bytes());
362 assert_eq!(msg_for_bob.as_slice(), dec_bob.as_bytes());
363 }
364
365 #[test]
366 fn test_ibe_wrong_key() {
367 let master = IbeMaster::generate();
368 let params = master.public_params();
369
370 let _alice_sk = master.extract_secret_key("alice@example.com");
371 let bob_sk = master.extract_secret_key("bob@example.com");
372
373 let ct = params.encrypt("alice@example.com", b"Secret").unwrap();
374
375 assert!(bob_sk.decrypt(&ct).is_err());
377 }
378
379 #[test]
380 fn test_ibe_node_ids() {
381 let master = IbeMaster::generate();
382 let params = master.public_params();
383
384 let node1_sk = master.extract_secret_key("node-12345");
385 let node2_sk = master.extract_secret_key("node-67890");
386
387 let msg = b"P2P message";
388 let ct = params.encrypt("node-12345", msg).unwrap();
389
390 let decrypted = node1_sk.decrypt(&ct).unwrap();
391 assert_eq!(msg.as_slice(), decrypted.as_bytes());
392
393 assert!(node2_sk.decrypt(&ct).is_err());
394 }
395
396 #[test]
397 fn test_ibe_empty_plaintext() {
398 let master = IbeMaster::generate();
399 let params = master.public_params();
400
401 let sk = master.extract_secret_key("test@example.com");
402
403 let ct = params.encrypt("test@example.com", b"").unwrap();
404 let decrypted = sk.decrypt(&ct).unwrap();
405
406 assert_eq!(decrypted.as_bytes(), b"");
407 }
408
409 #[test]
410 fn test_ibe_large_plaintext() {
411 let master = IbeMaster::generate();
412 let params = master.public_params();
413
414 let sk = master.extract_secret_key("test@example.com");
415
416 let plaintext = vec![0x42u8; 10000];
417 let ct = params.encrypt("test@example.com", &plaintext).unwrap();
418 let decrypted = sk.decrypt(&ct).unwrap();
419
420 assert_eq!(decrypted.as_bytes(), plaintext.as_slice());
421 }
422
423 #[test]
424 fn test_ibe_different_encryptions() {
425 let master = IbeMaster::generate();
426 let params = master.public_params();
427
428 let sk = master.extract_secret_key("test@example.com");
429 let msg = b"Same message";
430
431 let ct1 = params.encrypt("test@example.com", msg).unwrap();
432 let ct2 = params.encrypt("test@example.com", msg).unwrap();
433
434 assert_ne!(ct1.to_bytes(), ct2.to_bytes());
436
437 assert_eq!(sk.decrypt(&ct1).unwrap().as_bytes(), msg);
439 assert_eq!(sk.decrypt(&ct2).unwrap().as_bytes(), msg);
440 }
441
442 #[test]
443 fn test_ibe_secret_key_identity() {
444 let master = IbeMaster::generate();
445 let identity = "user@example.com";
446 let sk = master.extract_secret_key(identity);
447
448 assert_eq!(sk.identity(), identity);
449 }
450
451 #[test]
452 fn test_ibe_ciphertext_serialization() {
453 let master = IbeMaster::generate();
454 let params = master.public_params();
455 let sk = master.extract_secret_key("test@example.com");
456
457 let plaintext = b"Test message";
458 let ct = params.encrypt("test@example.com", plaintext).unwrap();
459
460 let serialized = ct.to_bytes();
461 let deserialized = IbeCiphertext::from_bytes(&serialized).unwrap();
462
463 let decrypted = sk.decrypt(&deserialized).unwrap();
464 assert_eq!(decrypted.as_bytes(), plaintext);
465 }
466
467 #[test]
468 fn test_ibe_secret_key_serialization() {
469 let master = IbeMaster::generate();
470 let params = master.public_params();
471
472 let sk = master.extract_secret_key("test@example.com");
473
474 let serialized = sk.to_bytes();
475 let deserialized = IbeSecretKey::from_bytes(&serialized).unwrap();
476
477 assert_eq!(deserialized.identity(), sk.identity());
478
479 let plaintext = b"Test message";
481 let ct = params.encrypt("test@example.com", plaintext).unwrap();
482
483 let decrypted = deserialized.decrypt(&ct).unwrap();
484 assert_eq!(decrypted.as_bytes(), plaintext);
485 }
486
487 #[test]
488 fn test_ibe_params_serialization() {
489 let master = IbeMaster::generate();
490 let params = master.public_params();
491 let sk = master.extract_secret_key("test@example.com");
492
493 let serialized = crate::codec::encode(¶ms).unwrap();
495 let deserialized: IbeParams = crate::codec::decode(&serialized).unwrap();
496
497 let plaintext = b"Test message";
499 let ct = deserialized.encrypt("test@example.com", plaintext).unwrap();
500
501 let decrypted = sk.decrypt(&ct).unwrap();
502 assert_eq!(decrypted.as_bytes(), plaintext);
503 }
504
505 #[test]
506 fn test_ibe_deterministic_key_extraction() {
507 let master = IbeMaster::generate();
508
509 let sk1 = master.extract_secret_key("test@example.com");
510 let sk2 = master.extract_secret_key("test@example.com");
511
512 assert_eq!(sk1.to_bytes(), sk2.to_bytes());
514 }
515
516 #[test]
517 fn test_ibe_corrupted_ciphertext() {
518 let master = IbeMaster::generate();
519 let params = master.public_params();
520 let sk = master.extract_secret_key("test@example.com");
521
522 let ct = params.encrypt("test@example.com", b"Test").unwrap();
523
524 let mut corrupted_bytes = ct.to_bytes();
525 corrupted_bytes[50] ^= 0xFF; let corrupted_ct = IbeCiphertext::from_bytes(&corrupted_bytes).unwrap();
528 assert!(sk.decrypt(&corrupted_ct).is_err());
529 }
530
531 #[test]
532 fn test_ibe_special_characters_in_identity() {
533 let master = IbeMaster::generate();
534 let params = master.public_params();
535
536 let identity = "user+tag@example.com";
537 let sk = master.extract_secret_key(identity);
538
539 let ct = params.encrypt(identity, b"Test").unwrap();
540 let decrypted = sk.decrypt(&ct).unwrap();
541
542 assert_eq!(decrypted.as_bytes(), b"Test");
543 }
544}