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_prekey_bundle: Option<KB>,
113
114 their_verifying_key: Option<PublicKey>,
116}
117
118impl<KMG, KB> TwoParty<KMG, KB>
121where
122 KMG: IdentityManager<KMG::State> + PreKeyManager,
123 KB: KeyBundle,
124{
125 pub fn init_to_send(their_prekey_bundle: KB) -> TwoPartyState<KB> {
128 TwoPartyState {
129 our_next_key_index: 1,
130 our_min_key_index: 1,
131 our_secret_keys: HashMap::new(),
132 our_received_secret_key: None,
133 their_verifying_key: None,
134 their_next_key_used: KeyUsed::PreKey,
135 their_prekey_bundle: Some(their_prekey_bundle),
136 }
137 }
138
139 pub fn init_to_receive() -> TwoPartyState<KB> {
141 TwoPartyState {
142 our_next_key_index: 1,
143 our_min_key_index: 1,
144 our_secret_keys: HashMap::new(),
145 our_received_secret_key: None,
146 their_verifying_key: None,
147 their_next_key_used: KeyUsed::PreKey,
148 their_prekey_bundle: None,
149 }
150 }
151
152 pub fn send(
154 y: TwoPartyState<KB>,
155 y_manager: &KMG::State,
156 plaintext: &[u8],
157 rng: &Rng,
158 ) -> TwoPartyResult<(TwoPartyState<KB>, TwoPartyMessage)> {
159 let (for_us, for_them) = Self::generate_keys(rng)?;
160
161 let plaintext_message = TwoPartyPlaintext {
162 plaintext: plaintext.to_vec(),
163 receiver_new_secret: for_them.their_new_secret.clone(),
164 sender_new_verifying_key: for_them.our_new_verifying_key,
165 sender_next_index: y.our_next_key_index,
166 };
167 let plaintext_bytes = plaintext_message.to_bytes()?;
168
169 let (mut y_i, ciphertext) = Self::encrypt(y, y_manager, &plaintext_bytes, rng)?;
170
171 let message = TwoPartyMessage {
172 ciphertext,
173 key_used: y_i.their_next_key_used,
174 };
175
176 y_i.our_secret_keys
177 .insert(y_i.our_next_key_index, for_us.our_new_secret);
178 y_i.our_next_key_index += 1;
179
180 y_i.their_verifying_key = Some(for_us.their_new_verifying_key);
181
182 y_i.their_next_key_used = KeyUsed::ReceivedKey;
183
184 Ok((y_i, message))
185 }
186
187 pub fn receive(
189 y: TwoPartyState<KB>,
190 y_manager: KMG::State,
191 message: TwoPartyMessage,
192 ) -> TwoPartyResult<(TwoPartyState<KB>, KMG::State, Vec<u8>)> {
193 let (mut y_i, y_manager_i, plaintext_bytes) =
194 Self::decrypt(y, y_manager, message.ciphertext, message.key_used)?;
195 let plaintext_message = TwoPartyPlaintext::from_bytes(&plaintext_bytes)?;
196
197 y_i.their_verifying_key = Some(plaintext_message.sender_new_verifying_key);
198 y_i.their_next_key_used = KeyUsed::OwnKey(plaintext_message.sender_next_index);
199 y_i.our_received_secret_key = Some(plaintext_message.receiver_new_secret);
200
201 Ok((y_i, y_manager_i, plaintext_message.plaintext))
202 }
203}
204
205#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
207#[allow(clippy::enum_variant_names)]
208pub enum KeyUsed {
209 PreKey,
211
212 ReceivedKey,
214
215 OwnKey(u64),
218}
219
220#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
225pub struct TwoPartyMessage {
226 ciphertext: TwoPartyCiphertext,
227 key_used: KeyUsed,
228}
229
230#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
231pub enum TwoPartyCiphertext {
232 PreKey(X3dhCiphertext),
234
235 Hpke(HpkeCiphertext),
237}
238
239#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
242pub struct TwoPartyPlaintext {
243 plaintext: Vec<u8>,
245
246 receiver_new_secret: SecretKey,
248
249 sender_new_verifying_key: PublicKey,
251
252 sender_next_index: u64,
255}
256
257impl TwoPartyPlaintext {
258 pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
259 decode_cbor(bytes)
260 }
261
262 pub fn to_bytes(&self) -> Result<Vec<u8>, EncodeError> {
263 encode_cbor(&self)
264 }
265}
266
267impl<KMG, KB> TwoParty<KMG, KB>
270where
271 KMG: IdentityManager<KMG::State> + PreKeyManager,
272 KB: KeyBundle,
273{
274 fn encrypt(
277 mut y: TwoPartyState<KB>,
278 y_manager: &KMG::State,
279 plaintext: &[u8],
280 rng: &Rng,
281 ) -> TwoPartyResult<(TwoPartyState<KB>, TwoPartyCiphertext)> {
282 let ciphertext = match &y.their_verifying_key {
283 None => {
284 let their_prekey_bundle = y
286 .their_prekey_bundle
287 .take()
288 .ok_or(TwoPartyError::PreKeyReuse)?;
289 let ciphertext = x3dh_encrypt(
290 plaintext,
291 KMG::identity_secret(y_manager),
292 &their_prekey_bundle,
293 rng,
294 )?;
295 TwoPartyCiphertext::PreKey(ciphertext)
296 }
297 Some(their_verifying_key) => {
298 let ciphertext = hpke_seal(their_verifying_key, None, None, plaintext)?;
299 TwoPartyCiphertext::Hpke(ciphertext)
300 }
301 };
302
303 Ok((y, ciphertext))
304 }
305
306 fn decrypt(
309 mut y: TwoPartyState<KB>,
310 y_manager: KMG::State,
311 ciphertext: TwoPartyCiphertext,
312 key_used: KeyUsed,
313 ) -> TwoPartyResult<(TwoPartyState<KB>, KMG::State, Vec<u8>)> {
314 let (y_manager_i, plaintext) = match key_used {
315 KeyUsed::PreKey => {
316 let TwoPartyCiphertext::PreKey(ciphertext) = ciphertext else {
317 return Err(TwoPartyError::InvalidCiphertextType);
318 };
319
320 let (y_manager_i, onetime_secret) = match ciphertext.onetime_prekey_id {
322 Some(onetime_prekey_id) => {
323 let (y_manager_i, onetime_secret) =
324 KMG::use_onetime_secret(y_manager, onetime_prekey_id)
325 .map_err(|_| TwoPartyError::PreKeyReuse)?;
326 (y_manager_i, onetime_secret)
327 }
328 None => (y_manager, None),
329 };
330
331 let plaintext = x3dh_decrypt(
332 &ciphertext,
333 KMG::identity_secret(&y_manager_i),
334 KMG::prekey_secret(&y_manager_i, &ciphertext.prekey_id)
335 .map_err(|_| TwoPartyError::UnknownPreKeyUsed(ciphertext.prekey_id))?,
337 onetime_secret.as_ref(),
338 )?;
339
340 (y_manager_i, plaintext)
341 }
342 KeyUsed::ReceivedKey => {
343 let TwoPartyCiphertext::Hpke(ciphertext) = ciphertext else {
344 return Err(TwoPartyError::InvalidCiphertextType);
345 };
346
347 let Some(our_received_secret_key) = &y.our_received_secret_key else {
348 return Err(TwoPartyError::UnknownSecretUsed(0));
349 };
350
351 let plaintext = hpke_open(&ciphertext, our_received_secret_key, None, None)?;
352 (y_manager, plaintext)
353 }
354 KeyUsed::OwnKey(index) => {
355 let TwoPartyCiphertext::Hpke(ciphertext) = ciphertext else {
356 return Err(TwoPartyError::InvalidCiphertextType);
357 };
358
359 let plaintext = match y.our_secret_keys.get(&index) {
360 Some(secret) => hpke_open(&ciphertext, secret, None, None)?,
361 None => return Err(TwoPartyError::UnknownSecretUsed(index)),
362 };
363
364 for i in y.our_min_key_index..index + 1 {
365 y.our_secret_keys.remove(&i);
366 }
367 y.our_min_key_index = index + 1;
368
369 (y_manager, plaintext)
370 }
371 };
372
373 Ok((y, y_manager_i, plaintext))
374 }
375}
376
377impl<KMG, KB> TwoParty<KMG, KB> {
378 fn generate_keys(rng: &Rng) -> TwoPartyResult<(NewKeysForUs, NewKeysForThem)> {
383 let our_new_secret = SecretKey::from_bytes(rng.random_array()?);
384 let our_new_verifying_key = our_new_secret.verifying_key()?;
385
386 let their_new_secret = SecretKey::from_bytes(rng.random_array()?);
387 let their_new_verifying_key = their_new_secret.verifying_key()?;
388
389 Ok((
390 NewKeysForUs {
391 our_new_secret,
392 their_new_verifying_key,
393 },
394 NewKeysForThem {
395 our_new_verifying_key,
396 their_new_secret,
397 },
398 ))
399 }
400}
401
402struct NewKeysForUs {
403 our_new_secret: SecretKey,
404 their_new_verifying_key: PublicKey,
405}
406
407struct NewKeysForThem {
408 our_new_verifying_key: PublicKey,
409 their_new_secret: SecretKey,
410}
411
412pub type TwoPartyResult<T> = Result<T, TwoPartyError>;
413
414#[derive(Debug, Error)]
415pub enum TwoPartyError {
416 #[error(transparent)]
417 Hpke(#[from] HpkeError),
418
419 #[error(transparent)]
420 X3dh(#[from] X3dhError),
421
422 #[error(transparent)]
423 Rng(#[from] RngError),
424
425 #[error(transparent)]
426 Encode(#[from] EncodeError),
427
428 #[error(transparent)]
429 Decode(#[from] DecodeError),
430
431 #[error(transparent)]
432 X25519(#[from] X25519Error),
433
434 #[error("prekeys have already been used")]
435 PreKeyReuse,
436
437 #[error("tried to decrypt with unknown 2SM secret at index {0}")]
438 UnknownSecretUsed(u64),
439
440 #[error("tried to decrypt with unknown initial X3DH pre-key {0}")]
441 UnknownPreKeyUsed(PreKeyId),
442
443 #[error("invalid ciphertext for message type")]
444 InvalidCiphertextType,
445}
446
447#[cfg(test)]
448mod tests {
449 use crate::crypto::Rng;
450 use crate::crypto::x25519::SecretKey;
451 use crate::key_bundle::Lifetime;
452 use crate::key_manager::KeyManager;
453 use crate::traits::PreKeyManager;
454
455 use super::{KeyUsed, LongTermTwoParty, OneTimeTwoParty, TwoPartyError};
456
457 #[test]
458 fn two_party_secret_messaging_protocol() {
459 let rng = Rng::from_seed([1; 32]);
460
461 let alice_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
464 let alice_manager =
465 KeyManager::init_and_generate_prekey(&alice_identity_secret, Lifetime::default(), &rng)
466 .unwrap();
467
468 let bob_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
471 let bob_manager =
472 KeyManager::init_and_generate_prekey(&bob_identity_secret, Lifetime::default(), &rng)
473 .unwrap();
474
475 let (bob_manager, bob_prekey_bundle) =
476 KeyManager::generate_onetime_bundle(bob_manager, &rng).unwrap();
477
478 let alice_2sm = OneTimeTwoParty::init_to_send(bob_prekey_bundle);
481
482 assert_eq!(alice_2sm.our_secret_keys.len(), 0);
484 assert_eq!(alice_2sm.our_min_key_index, 1);
485 assert_eq!(alice_2sm.our_next_key_index, 1);
486 assert_eq!(alice_2sm.their_next_key_used, KeyUsed::PreKey);
487
488 let bob_2sm = OneTimeTwoParty::init_to_receive();
489
490 assert_eq!(bob_2sm.our_secret_keys.len(), 0);
492 assert_eq!(bob_2sm.our_min_key_index, 1);
493 assert_eq!(bob_2sm.our_next_key_index, 1);
494 assert_eq!(bob_2sm.their_next_key_used, KeyUsed::PreKey);
495
496 let (alice_2sm, message_1) =
500 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, Bob!", &rng).unwrap();
501
502 assert_eq!(alice_2sm.our_secret_keys.len(), 1);
504 assert_eq!(alice_2sm.our_min_key_index, 1);
505 assert_eq!(alice_2sm.our_next_key_index, 2);
506
507 assert!(alice_2sm.their_verifying_key.is_some());
510
511 assert!(alice_2sm.our_received_secret_key.is_none());
513
514 assert_eq!(alice_2sm.their_next_key_used, KeyUsed::ReceivedKey);
516
517 assert!(alice_2sm.their_prekey_bundle.is_none());
519
520 let (bob_2sm, bob_manager, receive_1) =
522 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_1).unwrap();
523
524 assert_eq!(bob_2sm.our_secret_keys.len(), 0);
526 assert_eq!(bob_2sm.our_min_key_index, 1);
527 assert_eq!(bob_2sm.our_next_key_index, 1);
528
529 assert_eq!(
531 bob_2sm
532 .their_verifying_key
533 .expect("bob learned about public key of alice"),
534 alice_2sm
535 .our_secret_keys
536 .get(&1)
537 .expect("alice has one secret key")
538 .verifying_key()
539 .unwrap()
540 );
541
542 assert!(bob_2sm.our_received_secret_key.is_some());
544
545 assert_eq!(bob_2sm.their_next_key_used, KeyUsed::OwnKey(1));
547
548 assert!(bob_2sm.their_prekey_bundle.is_none());
550
551 let (alice_2sm, message_2) =
553 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"How are you doing?", &rng).unwrap();
554 let (bob_2sm, bob_manager, receive_2) =
555 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2).unwrap();
556
557 assert_eq!(alice_2sm.our_secret_keys.len(), 2);
559 assert_eq!(alice_2sm.our_min_key_index, 1);
560 assert_eq!(alice_2sm.our_next_key_index, 3);
561
562 assert_ne!(
564 alice_2sm.our_secret_keys.get(&1).unwrap(),
565 alice_2sm.our_secret_keys.get(&2).unwrap(),
566 );
567
568 assert_eq!(
570 bob_2sm
571 .their_verifying_key
572 .expect("bob learned about public key of alice"),
573 alice_2sm
574 .our_secret_keys
575 .get(&2)
576 .expect("alice has one secret key")
577 .verifying_key()
578 .unwrap()
579 );
580
581 let (bob_2sm, message_3) =
583 OneTimeTwoParty::send(bob_2sm, &bob_manager, b"I'm alright. Thank you!", &rng).unwrap();
584
585 assert_eq!(message_3.key_used, KeyUsed::OwnKey(2));
587
588 assert_eq!(bob_2sm.our_secret_keys.len(), 1);
590 assert_eq!(bob_2sm.our_min_key_index, 1);
591 assert_eq!(bob_2sm.our_next_key_index, 2);
592
593 assert_eq!(bob_2sm.their_next_key_used, KeyUsed::ReceivedKey);
595
596 let (alice_2sm, alice_manager, receive_3) =
598 OneTimeTwoParty::receive(alice_2sm, alice_manager, message_3).unwrap();
599
600 assert_eq!(alice_2sm.our_secret_keys.len(), 0);
603 assert_eq!(alice_2sm.our_min_key_index, 3);
604 assert_eq!(alice_2sm.our_next_key_index, 3);
605
606 let (bob_2sm, message_4) =
608 OneTimeTwoParty::send(bob_2sm, &bob_manager, b"How are you?", &rng).unwrap();
609 let (alice_2sm, alice_manager, receive_4) =
610 OneTimeTwoParty::receive(alice_2sm, alice_manager, message_4).unwrap();
611
612 let (alice_2sm, message_5) =
613 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"I'm bored.", &rng).unwrap();
614 let (bob_2sm, bob_manager, receive_5) =
615 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_5).unwrap();
616
617 assert_eq!(receive_1, b"Hello, Bob!");
619 assert_eq!(receive_2, b"How are you doing?");
620 assert_eq!(receive_3, b"I'm alright. Thank you!");
621 assert_eq!(receive_4, b"How are you?");
622 assert_eq!(receive_5, b"I'm bored.");
623
624 let (bob_2sm, message_6) =
626 OneTimeTwoParty::send(bob_2sm, &bob_manager, b":-(", &rng).unwrap();
627 let (alice_2sm, message_7) =
628 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Oh wait.", &rng).unwrap();
629
630 let (alice_2sm, _, receive_6) =
631 OneTimeTwoParty::receive(alice_2sm, alice_manager, message_6).unwrap();
632 let (bob_2sm, _, receive_7) =
633 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_7).unwrap();
634
635 assert_eq!(receive_6, b":-(");
636 assert_eq!(receive_7, b"Oh wait.");
637
638 assert_eq!(alice_2sm.our_secret_keys.len(), 1);
640 assert_eq!(bob_2sm.our_secret_keys.len(), 1);
641 }
642
643 #[test]
644 fn long_term_prekeys() {
645 let rng = Rng::from_seed([1; 32]);
646
647 let alice_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
650 let alice_manager =
651 KeyManager::init_and_generate_prekey(&alice_identity_secret, Lifetime::default(), &rng)
652 .unwrap();
653
654 let bob_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
657 let bob_manager =
658 KeyManager::init_and_generate_prekey(&bob_identity_secret, Lifetime::default(), &rng)
659 .unwrap();
660
661 let bob_prekey_bundle = KeyManager::prekey_bundle(&bob_manager).unwrap();
662
663 let alice_2sm_a = LongTermTwoParty::init_to_send(bob_prekey_bundle.clone());
666 let bob_2sm_a = LongTermTwoParty::init_to_receive();
667
668 let (alice_2sm_a, message_1) =
671 LongTermTwoParty::send(alice_2sm_a, &alice_manager, b"Hello, Bob!", &rng).unwrap();
672
673 let bob_verifying_key_1 = alice_2sm_a.their_verifying_key;
675
676 let (bob_2sm_a, bob_manager, receive_1) =
677 LongTermTwoParty::receive(bob_2sm_a, bob_manager, message_1).unwrap();
678
679 let (_bob_2sm_a, message_2) =
680 LongTermTwoParty::send(bob_2sm_a, &bob_manager, b"Hello, Alice!", &rng).unwrap();
681 let (_alice_2sm_a, alice_manager, receive_2) =
682 LongTermTwoParty::receive(alice_2sm_a, alice_manager, message_2).unwrap();
683
684 assert_eq!(receive_1, b"Hello, Bob!");
685 assert_eq!(receive_2, b"Hello, Alice!");
686
687 let alice_2sm_b = LongTermTwoParty::init_to_send(bob_prekey_bundle);
690 let bob_2sm_b = LongTermTwoParty::init_to_receive();
691
692 let (alice_2sm_b, message_1) =
695 LongTermTwoParty::send(alice_2sm_b, &alice_manager, b"Hello, again, Bob!", &rng)
696 .unwrap();
697
698 let bob_verifying_key_2 = alice_2sm_b.their_verifying_key;
700
701 let (bob_2sm_b, bob_manager, receive_1) =
702 LongTermTwoParty::receive(bob_2sm_b, bob_manager, message_1).unwrap();
703
704 let (_bob_2sm_b, message_2) =
705 LongTermTwoParty::send(bob_2sm_b, &bob_manager, b"Hello, again, Alice!", &rng).unwrap();
706 let (_alice_2sm_b, _alice_manager, receive_2) =
707 LongTermTwoParty::receive(alice_2sm_b, alice_manager, message_2).unwrap();
708
709 assert_eq!(receive_1, b"Hello, again, Bob!");
710 assert_eq!(receive_2, b"Hello, again, Alice!");
711
712 assert_ne!(bob_verifying_key_1, bob_verifying_key_2);
715 }
716
717 #[test]
718 fn invalid_replayed_messages() {
719 let rng = Rng::from_seed([1; 32]);
720
721 let alice_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
724 let alice_manager =
725 KeyManager::init_and_generate_prekey(&alice_identity_secret, Lifetime::default(), &rng)
726 .unwrap();
727
728 let bob_identity_secret = SecretKey::from_bytes(rng.random_array().unwrap());
731 let bob_manager =
732 KeyManager::init_and_generate_prekey(&bob_identity_secret, Lifetime::default(), &rng)
733 .unwrap();
734
735 let (bob_manager, bob_prekey_bundle) =
736 KeyManager::generate_onetime_bundle(bob_manager, &rng).unwrap();
737
738 let alice_2sm = OneTimeTwoParty::init_to_send(bob_prekey_bundle);
741 let bob_2sm = OneTimeTwoParty::init_to_receive();
742
743 let (alice_2sm, message_1) =
746 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, Bob!", &rng).unwrap();
747 let (bob_2sm, bob_manager, _receive_1) =
748 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_1.clone()).unwrap();
749
750 let result = OneTimeTwoParty::receive(bob_2sm.clone(), bob_manager.clone(), message_1);
753 std::assert_matches!(result, Err(TwoPartyError::PreKeyReuse));
754
755 let (_alice_2sm, message_2) =
758 OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, again, Bob!", &rng).unwrap();
759 let (bob_2sm, bob_manager, _receive_2) =
760 OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2.clone()).unwrap();
761
762 let result = OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2);
765 std::assert_matches!(result, Err(TwoPartyError::Hpke(_)));
766 }
767}