1use std::collections::HashMap;
5use std::marker::PhantomData;
6
7use p2panda_core::cbor::{DecodeError, EncodeError, decode_cbor, encode_cbor};
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10
11use crate::crypto::hpke::{HpkeCiphertext, HpkeError, hpke_open, hpke_seal};
12use crate::crypto::x25519::{PublicKey, SecretKey, X25519Error};
13use crate::crypto::{Rng, RngError};
14use crate::key_bundle::{LongTermKeyBundle, OneTimeKeyBundle, PreKeyId};
15use crate::key_manager::KeyManager;
16use crate::traits::{IdentityManager, KeyBundle, PreKeyManager};
17use crate::two_party::{X3dhCiphertext, X3dhError, x3dh_decrypt, x3dh_encrypt};
18
19pub struct TwoParty<KMG, KB> {
73 _marker: PhantomData<(KMG, KB)>,
74}
75
76pub type OneTimeTwoParty = TwoParty<KeyManager, OneTimeKeyBundle>;
78
79pub type LongTermTwoParty = TwoParty<KeyManager, LongTermKeyBundle>;
81
82#[derive(Debug, Serialize, Deserialize)]
90#[cfg_attr(any(test, feature = "test_utils"), derive(Clone))]
91pub struct TwoPartyState<KB: KeyBundle> {
92 our_next_key_index: u64,
95
96 our_min_key_index: u64,
99
100 our_secret_keys: HashMap<u64, SecretKey>,
103
104 our_received_secret_key: Option<SecretKey>,
107
108 their_next_key_used: KeyUsed,
110
111 their_identity_key: PublicKey,
113
114 their_prekey_bundle: Option<KB>,
116
117 their_public_key: Option<PublicKey>,
119}
120
121impl<KMG, KB> TwoParty<KMG, KB>
124where
125 KMG: IdentityManager<KMG::State> + PreKeyManager,
126 KB: KeyBundle,
127{
128 pub fn init(their_prekey_bundle: KB) -> TwoPartyState<KB> {
130 TwoPartyState {
131 our_next_key_index: 1,
132 our_min_key_index: 1,
133 our_secret_keys: HashMap::new(),
134 our_received_secret_key: None,
135 their_identity_key: *their_prekey_bundle.identity_key(),
136 their_public_key: None,
137 their_next_key_used: KeyUsed::PreKey,
138 their_prekey_bundle: Some(their_prekey_bundle),
139 }
140 }
141
142 pub fn send(
144 y: TwoPartyState<KB>,
145 y_manager: &KMG::State,
146 plaintext: &[u8],
147 rng: &Rng,
148 ) -> TwoPartyResult<(TwoPartyState<KB>, TwoPartyMessage)> {
149 let (for_us, for_them) = Self::generate_keys(rng)?;
150
151 let plaintext_message = TwoPartyPlaintext {
152 plaintext: plaintext.to_vec(),
153 receiver_new_secret: for_them.their_new_secret.clone(),
154 sender_new_public_key: for_them.our_new_public_key,
155 sender_next_index: y.our_next_key_index,
156 };
157 let plaintext_bytes = plaintext_message.to_bytes()?;
158
159 let (mut y_i, ciphertext) = Self::encrypt(y, y_manager, &plaintext_bytes, rng)?;
160
161 let message = TwoPartyMessage {
162 ciphertext,
163 key_used: y_i.their_next_key_used,
164 };
165
166 y_i.our_secret_keys
167 .insert(y_i.our_next_key_index, for_us.our_new_secret);
168 y_i.our_next_key_index += 1;
169
170 y_i.their_public_key = Some(for_us.their_new_public_key);
171
172 y_i.their_next_key_used = KeyUsed::ReceivedKey;
173
174 Ok((y_i, message))
175 }
176
177 pub fn receive(
179 y: TwoPartyState<KB>,
180 y_manager: KMG::State,
181 message: TwoPartyMessage,
182 ) -> TwoPartyResult<(TwoPartyState<KB>, KMG::State, Vec<u8>)> {
183 let (mut y_i, y_manager_i, plaintext_bytes) =
184 Self::decrypt(y, y_manager, message.ciphertext, message.key_used)?;
185 let plaintext_message = TwoPartyPlaintext::from_bytes(&plaintext_bytes)?;
186
187 y_i.their_public_key = Some(plaintext_message.sender_new_public_key);
188 y_i.their_next_key_used = KeyUsed::OwnKey(plaintext_message.sender_next_index);
189 y_i.our_received_secret_key = Some(plaintext_message.receiver_new_secret);
190
191 Ok((y_i, y_manager_i, plaintext_message.plaintext))
192 }
193}
194
195#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
197#[allow(clippy::enum_variant_names)]
198pub enum KeyUsed {
199 PreKey,
201
202 ReceivedKey,
204
205 OwnKey(u64),
208}
209
210#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
215pub struct TwoPartyMessage {
216 ciphertext: TwoPartyCiphertext,
217 key_used: KeyUsed,
218}
219
220#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
221pub enum TwoPartyCiphertext {
222 PreKey(X3dhCiphertext),
224
225 Hpke(HpkeCiphertext),
227}
228
229#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
232pub struct TwoPartyPlaintext {
233 plaintext: Vec<u8>,
235
236 receiver_new_secret: SecretKey,
238
239 sender_new_public_key: PublicKey,
241
242 sender_next_index: u64,
245}
246
247impl TwoPartyPlaintext {
248 pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
249 decode_cbor(bytes)
250 }
251
252 pub fn to_bytes(&self) -> Result<Vec<u8>, EncodeError> {
253 encode_cbor(&self)
254 }
255}
256
257impl<KMG, KB> TwoParty<KMG, KB>
260where
261 KMG: IdentityManager<KMG::State> + PreKeyManager,
262 KB: KeyBundle,
263{
264 fn encrypt(
267 mut y: TwoPartyState<KB>,
268 y_manager: &KMG::State,
269 plaintext: &[u8],
270 rng: &Rng,
271 ) -> TwoPartyResult<(TwoPartyState<KB>, TwoPartyCiphertext)> {
272 let ciphertext = match &y.their_public_key {
273 None => {
274 let their_prekey_bundle = y
276 .their_prekey_bundle
277 .take()
278 .ok_or(TwoPartyError::PreKeyReuse)?;
279 let ciphertext = x3dh_encrypt(
280 plaintext,
281 KMG::identity_secret(y_manager),
282 &their_prekey_bundle,
283 rng,
284 )?;
285 TwoPartyCiphertext::PreKey(ciphertext)
286 }
287 Some(their_public_key) => {
288 let ciphertext = hpke_seal(their_public_key, None, None, plaintext)?;
289 TwoPartyCiphertext::Hpke(ciphertext)
290 }
291 };
292
293 Ok((y, ciphertext))
294 }
295
296 fn decrypt(
299 mut y: TwoPartyState<KB>,
300 y_manager: KMG::State,
301 ciphertext: TwoPartyCiphertext,
302 key_used: KeyUsed,
303 ) -> TwoPartyResult<(TwoPartyState<KB>, KMG::State, Vec<u8>)> {
304 let (y_manager_i, plaintext) = match key_used {
305 KeyUsed::PreKey => {
306 let TwoPartyCiphertext::PreKey(ciphertext) = ciphertext else {
307 return Err(TwoPartyError::InvalidCiphertextType);
308 };
309
310 let (y_manager_i, onetime_secret) = match ciphertext.onetime_prekey_id {
312 Some(onetime_prekey_id) => {
313 let (y_manager_i, onetime_secret) =
314 KMG::use_onetime_secret(y_manager, onetime_prekey_id)
315 .map_err(|_| TwoPartyError::PreKeyReuse)?;
316 (y_manager_i, onetime_secret)
317 }
318 None => (y_manager, None),
319 };
320
321 let plaintext = x3dh_decrypt(
322 &ciphertext,
323 KMG::identity_secret(&y_manager_i),
324 KMG::prekey_secret(&y_manager_i, &ciphertext.prekey_id)
325 .map_err(|_| TwoPartyError::UnknownPreKeyUsed(ciphertext.prekey_id))?,
327 onetime_secret.as_ref(),
328 )?;
329
330 (y_manager_i, plaintext)
331 }
332 KeyUsed::ReceivedKey => {
333 let TwoPartyCiphertext::Hpke(ciphertext) = ciphertext else {
334 return Err(TwoPartyError::InvalidCiphertextType);
335 };
336
337 let Some(our_received_secret_key) = &y.our_received_secret_key else {
338 return Err(TwoPartyError::UnknownSecretUsed(0));
339 };
340
341 let plaintext = hpke_open(&ciphertext, our_received_secret_key, None, None)?;
342 (y_manager, plaintext)
343 }
344 KeyUsed::OwnKey(index) => {
345 let TwoPartyCiphertext::Hpke(ciphertext) = ciphertext else {
346 return Err(TwoPartyError::InvalidCiphertextType);
347 };
348
349 let plaintext = match y.our_secret_keys.get(&index) {
350 Some(secret) => hpke_open(&ciphertext, secret, None, None)?,
351 None => return Err(TwoPartyError::UnknownSecretUsed(index)),
352 };
353
354 for i in y.our_min_key_index..index + 1 {
355 y.our_secret_keys.remove(&i);
356 }
357 y.our_min_key_index = index + 1;
358
359 (y_manager, plaintext)
360 }
361 };
362
363 Ok((y, y_manager_i, plaintext))
364 }
365}
366
367impl<KMG, KB> TwoParty<KMG, KB> {
368 fn generate_keys(rng: &Rng) -> TwoPartyResult<(NewKeysForUs, NewKeysForThem)> {
373 let our_new_secret = SecretKey::from_bytes(rng.random_array()?);
374 let our_new_public_key = our_new_secret.public_key()?;
375
376 let their_new_secret = SecretKey::from_bytes(rng.random_array()?);
377 let their_new_public_key = their_new_secret.public_key()?;
378
379 Ok((
380 NewKeysForUs {
381 our_new_secret,
382 their_new_public_key,
383 },
384 NewKeysForThem {
385 our_new_public_key,
386 their_new_secret,
387 },
388 ))
389 }
390}
391
392struct NewKeysForUs {
393 our_new_secret: SecretKey,
394 their_new_public_key: PublicKey,
395}
396
397struct NewKeysForThem {
398 our_new_public_key: PublicKey,
399 their_new_secret: SecretKey,
400}
401
402pub type TwoPartyResult<T> = Result<T, TwoPartyError>;
403
404#[derive(Debug, Error)]
405pub enum TwoPartyError {
406 #[error(transparent)]
407 Hpke(#[from] HpkeError),
408
409 #[error(transparent)]
410 X3dh(#[from] X3dhError),
411
412 #[error(transparent)]
413 Rng(#[from] RngError),
414
415 #[error(transparent)]
416 Encode(#[from] EncodeError),
417
418 #[error(transparent)]
419 Decode(#[from] DecodeError),
420
421 #[error(transparent)]
422 X25519(#[from] X25519Error),
423
424 #[error("prekeys have already been used")]
425 PreKeyReuse,
426
427 #[error("tried to decrypt with unknown 2SM secret at index {0}")]
428 UnknownSecretUsed(u64),
429
430 #[error("tried to decrypt with unknown initial X3DH pre-key {0}")]
431 UnknownPreKeyUsed(PreKeyId),
432
433 #[error("invalid ciphertext for message type")]
434 InvalidCiphertextType,
435}
436
437#[cfg(test)]
438mod tests {
439 use crate::crypto::Rng;
440 use crate::crypto::x25519::SecretKey;
441 use crate::key_bundle::Lifetime;
442 use crate::key_manager::KeyManager;
443 use crate::traits::PreKeyManager;
444
445 use super::{KeyUsed, LongTermTwoParty, OneTimeTwoParty, TwoPartyError};
446
447 #[test]
448 fn two_party_secret_messaging_protocol() {
449 let rng = Rng::from_seed([1; 32]);
450
451 let alice_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
454 let alice_manager =
455 KeyManager::init_and_generate_prekey(&alice_identity_secret, Lifetime::default(), &rng)
456 .unwrap();
457
458 let (alice_manager, alice_prekey_bundle) =
459 KeyManager::generate_onetime_bundle(alice_manager, &rng).unwrap();
460
461 let bob_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
464 let bob_manager =
465 KeyManager::init_and_generate_prekey(&bob_identity_secret, Lifetime::default(), &rng)
466 .unwrap();
467
468 let (bob_manager, bob_prekey_bundle) =
469 KeyManager::generate_onetime_bundle(bob_manager, &rng).unwrap();
470
471 let alice_2sm = OneTimeTwoParty::init(bob_prekey_bundle);
474
475 assert_eq!(alice_2sm.our_secret_keys.len(), 0);
477 assert_eq!(alice_2sm.our_min_key_index, 1);
478 assert_eq!(alice_2sm.our_next_key_index, 1);
479 assert_eq!(alice_2sm.their_next_key_used, KeyUsed::PreKey);
480
481 let bob_2sm = OneTimeTwoParty::init(alice_prekey_bundle);
482
483 assert_eq!(bob_2sm.our_secret_keys.len(), 0);
485 assert_eq!(bob_2sm.our_min_key_index, 1);
486 assert_eq!(bob_2sm.our_next_key_index, 1);
487 assert_eq!(bob_2sm.their_next_key_used, KeyUsed::PreKey);
488
489 let (alice_2sm, message_1) =
493 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, Bob!", &rng).unwrap();
494
495 assert_eq!(alice_2sm.our_secret_keys.len(), 1);
497 assert_eq!(alice_2sm.our_min_key_index, 1);
498 assert_eq!(alice_2sm.our_next_key_index, 2);
499
500 assert!(alice_2sm.their_public_key.is_some());
503
504 assert!(alice_2sm.our_received_secret_key.is_none());
506
507 assert_eq!(alice_2sm.their_next_key_used, KeyUsed::ReceivedKey);
509
510 assert!(alice_2sm.their_prekey_bundle.is_none());
512
513 let (bob_2sm, bob_manager, receive_1) =
515 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_1).unwrap();
516
517 assert_eq!(bob_2sm.our_secret_keys.len(), 0);
519 assert_eq!(bob_2sm.our_min_key_index, 1);
520 assert_eq!(bob_2sm.our_next_key_index, 1);
521
522 assert_eq!(
524 bob_2sm
525 .their_public_key
526 .expect("bob learned about public key of alice"),
527 alice_2sm
528 .our_secret_keys
529 .get(&1)
530 .expect("alice has one secret key")
531 .public_key()
532 .unwrap()
533 );
534
535 assert!(bob_2sm.our_received_secret_key.is_some());
537
538 assert_eq!(bob_2sm.their_next_key_used, KeyUsed::OwnKey(1));
540
541 assert!(bob_2sm.their_prekey_bundle.is_some());
543
544 let (alice_2sm, message_2) =
546 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"How are you doing?", &rng).unwrap();
547 let (bob_2sm, bob_manager, receive_2) =
548 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2).unwrap();
549
550 assert_eq!(alice_2sm.our_secret_keys.len(), 2);
552 assert_eq!(alice_2sm.our_min_key_index, 1);
553 assert_eq!(alice_2sm.our_next_key_index, 3);
554
555 assert_ne!(
557 alice_2sm.our_secret_keys.get(&1).unwrap(),
558 alice_2sm.our_secret_keys.get(&2).unwrap(),
559 );
560
561 assert_eq!(
563 bob_2sm
564 .their_public_key
565 .expect("bob learned about public key of alice"),
566 alice_2sm
567 .our_secret_keys
568 .get(&2)
569 .expect("alice has one secret key")
570 .public_key()
571 .unwrap()
572 );
573
574 let (bob_2sm, message_3) =
576 OneTimeTwoParty::send(bob_2sm, &bob_manager, b"I'm alright. Thank you!", &rng).unwrap();
577
578 assert_eq!(message_3.key_used, KeyUsed::OwnKey(2));
580
581 assert_eq!(bob_2sm.our_secret_keys.len(), 1);
583 assert_eq!(bob_2sm.our_min_key_index, 1);
584 assert_eq!(bob_2sm.our_next_key_index, 2);
585
586 assert_eq!(bob_2sm.their_next_key_used, KeyUsed::ReceivedKey);
588
589 let (alice_2sm, alice_manager, receive_3) =
591 OneTimeTwoParty::receive(alice_2sm, alice_manager, message_3).unwrap();
592
593 assert_eq!(alice_2sm.our_secret_keys.len(), 0);
596 assert_eq!(alice_2sm.our_min_key_index, 3);
597 assert_eq!(alice_2sm.our_next_key_index, 3);
598
599 let (bob_2sm, message_4) =
601 OneTimeTwoParty::send(bob_2sm, &bob_manager, b"How are you?", &rng).unwrap();
602 let (alice_2sm, alice_manager, receive_4) =
603 OneTimeTwoParty::receive(alice_2sm, alice_manager, message_4).unwrap();
604
605 let (alice_2sm, message_5) =
606 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"I'm bored.", &rng).unwrap();
607 let (bob_2sm, bob_manager, receive_5) =
608 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_5).unwrap();
609
610 assert_eq!(receive_1, b"Hello, Bob!");
612 assert_eq!(receive_2, b"How are you doing?");
613 assert_eq!(receive_3, b"I'm alright. Thank you!");
614 assert_eq!(receive_4, b"How are you?");
615 assert_eq!(receive_5, b"I'm bored.");
616
617 let (bob_2sm, message_6) =
619 OneTimeTwoParty::send(bob_2sm, &bob_manager, b":-(", &rng).unwrap();
620 let (alice_2sm, message_7) =
621 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Oh wait.", &rng).unwrap();
622
623 let (alice_2sm, _, receive_6) =
624 OneTimeTwoParty::receive(alice_2sm, alice_manager, message_6).unwrap();
625 let (bob_2sm, _, receive_7) =
626 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_7).unwrap();
627
628 assert_eq!(receive_6, b":-(");
629 assert_eq!(receive_7, b"Oh wait.");
630
631 assert_eq!(alice_2sm.our_secret_keys.len(), 1);
633 assert_eq!(bob_2sm.our_secret_keys.len(), 1);
634 }
635
636 #[test]
637 fn long_term_prekeys() {
638 let rng = Rng::from_seed([1; 32]);
639
640 let alice_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
643 let alice_manager =
644 KeyManager::init_and_generate_prekey(&alice_identity_secret, Lifetime::default(), &rng)
645 .unwrap();
646
647 let alice_prekey_bundle = KeyManager::prekey_bundle(&alice_manager).unwrap();
648
649 let bob_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
652 let bob_manager =
653 KeyManager::init_and_generate_prekey(&bob_identity_secret, Lifetime::default(), &rng)
654 .unwrap();
655
656 let bob_prekey_bundle = KeyManager::prekey_bundle(&bob_manager).unwrap();
657
658 let alice_2sm_a = LongTermTwoParty::init(bob_prekey_bundle.clone());
661 let bob_2sm_a = LongTermTwoParty::init(alice_prekey_bundle.clone());
662
663 let (alice_2sm_a, message_1) =
666 LongTermTwoParty::send(alice_2sm_a, &alice_manager, b"Hello, Bob!", &rng).unwrap();
667
668 let bob_public_key_1 = alice_2sm_a.their_public_key;
670
671 let (bob_2sm_a, bob_manager, receive_1) =
672 LongTermTwoParty::receive(bob_2sm_a, bob_manager, message_1).unwrap();
673
674 let (_bob_2sm_a, message_2) =
675 LongTermTwoParty::send(bob_2sm_a, &bob_manager, b"Hello, Alice!", &rng).unwrap();
676 let (_alice_2sm_a, alice_manager, receive_2) =
677 LongTermTwoParty::receive(alice_2sm_a, alice_manager, message_2).unwrap();
678
679 assert_eq!(receive_1, b"Hello, Bob!");
680 assert_eq!(receive_2, b"Hello, Alice!");
681
682 let alice_2sm_b = LongTermTwoParty::init(bob_prekey_bundle);
685 let bob_2sm_b = LongTermTwoParty::init(alice_prekey_bundle);
686
687 let (alice_2sm_b, message_1) =
690 LongTermTwoParty::send(alice_2sm_b, &alice_manager, b"Hello, again, Bob!", &rng)
691 .unwrap();
692
693 let bob_public_key_2 = alice_2sm_b.their_public_key;
695
696 let (bob_2sm_b, bob_manager, receive_1) =
697 LongTermTwoParty::receive(bob_2sm_b, bob_manager, message_1).unwrap();
698
699 let (_bob_2sm_b, message_2) =
700 LongTermTwoParty::send(bob_2sm_b, &bob_manager, b"Hello, again, Alice!", &rng).unwrap();
701 let (_alice_2sm_b, _alice_manager, receive_2) =
702 LongTermTwoParty::receive(alice_2sm_b, alice_manager, message_2).unwrap();
703
704 assert_eq!(receive_1, b"Hello, again, Bob!");
705 assert_eq!(receive_2, b"Hello, again, Alice!");
706
707 assert_ne!(bob_public_key_1, bob_public_key_2);
710 }
711
712 #[test]
713 fn invalid_replayed_messages() {
714 let rng = Rng::from_seed([1; 32]);
715
716 let alice_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
719 let alice_manager =
720 KeyManager::init_and_generate_prekey(&alice_identity_secret, Lifetime::default(), &rng)
721 .unwrap();
722
723 let (alice_manager, alice_prekey_bundle) =
724 KeyManager::generate_onetime_bundle(alice_manager, &rng).unwrap();
725
726 let bob_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
729 let bob_manager =
730 KeyManager::init_and_generate_prekey(&bob_identity_secret, Lifetime::default(), &rng)
731 .unwrap();
732
733 let (bob_manager, bob_prekey_bundle) =
734 KeyManager::generate_onetime_bundle(bob_manager, &rng).unwrap();
735
736 let alice_2sm = OneTimeTwoParty::init(bob_prekey_bundle);
739 let bob_2sm = OneTimeTwoParty::init(alice_prekey_bundle);
740
741 let (alice_2sm, message_1) =
744 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, Bob!", &rng).unwrap();
745 let (bob_2sm, bob_manager, _receive_1) =
746 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_1.clone()).unwrap();
747
748 let result = OneTimeTwoParty::receive(bob_2sm.clone(), bob_manager.clone(), message_1);
751 assert!(matches!(result, Err(TwoPartyError::PreKeyReuse)));
752
753 let (_alice_2sm, message_2) =
756 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, again, Bob!", &rng).unwrap();
757 let (bob_2sm, bob_manager, _receive_2) =
758 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2.clone()).unwrap();
759
760 let result = OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2);
763 assert!(matches!(result, Err(TwoPartyError::Hpke(_))));
764 }
765}