Skip to main content

p2panda_encryption/two_party/
two_party.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Two-Party Secure Messaging (2SM) Key Agreement Protocol.
4use 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
19/// Two-Party Secure Messaging (2SM) Key Agreement Protocol as specified in the paper "Key
20/// Agreement for Decentralized Secure Group Messaging with Strong Security Guarantees" (2020).
21///
22/// 2SM is used for key-agreement as part of the DCGKA protocol allowing all members to learn about
23/// the "seed" for establishing new secret state. 2SM is pair-wise between all members of an
24/// encrypted group. p2panda uses 2SM for both "data-" and "message encryption" schemes.
25///
26/// ## Protocol
27///
28/// An initiator "Alice" of a 2SM session uses the pre-keys of "Bob" to send the first encrypted
29/// message using the X3DH protocol. This only takes place once and the pre-keys can be considered
30/// "used" afterwards (which is especially important for one-time pre-keys).
31///
32/// All subsequent messages sent between Alice and Bob are encrypted using the HPKE protocol. For
33/// each round the sender uses the previous keys for HPKE and generates and attaches to the payload
34/// a new key-pair for future rounds.
35///
36/// To avoid reusing public keys (which would make FS impossible), whenever a party sends a
37/// message, it also updates the other party's public key. To do so, it sends a new secret key
38/// along with its message, then deletes its own copy, storing only the public key.
39///
40/// To accommodate for messages arriving "late", the secret key is kept until it or a newer secret
41/// has been used. In the case of a newer secret being used, all "previous" secret keys will be
42/// dropped.
43///
44/// ## Forward secrecy
45///
46/// During the initial 2SM "round" using X3DH the forward secrecy is defined by the lifetime of the
47/// used pre-keys. For strong security guarantees it is recommended to use one-time pre-keys. If
48/// this requirement can be relaxed it is possible to use long-term pre-keys, with a lifetime
49/// defined by the application.
50///
51/// Each subsequent 2SM HPKE round uses exactly one secret key, which is then dropped and replaced
52/// by a newly-generated key-pair. This gives the key-agreement protocol strong forward secrecy
53/// guarantees for each round, independent of the used pre-keys.
54///
55/// ## Cost of key-agreements
56///
57/// To make a group aware of a new secret key we could encrypt the secret pairwise with public-key
58/// encryption (PKE) towards each member of the group, resulting in an O(n^2) overhead as every
59/// member needs to share their secret with every other. The paper proposes an alternative approach
60/// with 2SM where a member prepares the next encryption keys not only for themselves but also for
61/// the other party, resulting in a more optimal O(n) cost when rotating keys. This allows us to
62/// "heal" the group in less steps after a member is removed.
63///
64/// ## Message Ordering
65///
66/// 2SM assumes that all messages are received in the order they have been sent. The application or
67/// underlying networking protocol needs to handle ordering. This is handled for us by the DCGKA
68/// protocol (as specified in the paper) and causally-ordered, authenticated broadcast in p2panda
69/// itself.
70///
71/// <https://eprint.iacr.org/2020/1281.pdf>
72pub struct TwoParty<KMG, KB> {
73    _marker: PhantomData<(KMG, KB)>,
74}
75
76/// 2SM protocol with one-time pre-keys.
77pub type OneTimeTwoParty = TwoParty<KeyManager, OneTimeKeyBundle>;
78
79/// 2SM protocol with long-term pre-keys (with a specified lifetime).
80pub type LongTermTwoParty = TwoParty<KeyManager, LongTermKeyBundle>;
81
82/// State of 2SM session between two members.
83///
84/// All 2SM methods are expressed as "pure functions" without any side-effects, returning an
85/// updated state object. This allows applications to be more crash-resiliant, persisting the final
86/// state only when all processes have successfully completed.
87///
88/// The state is serializable and can be used to persist 2SM sessions.
89#[derive(Debug, Serialize, Deserialize)]
90#[cfg_attr(any(test, feature = "test_utils"), derive(Clone))]
91pub struct TwoPartyState<KB: KeyBundle> {
92    /// Index of key we will use during next send. The receiver can use the public key and refer to
93    /// it through that index when they want to encrypt a message back to us.
94    our_next_key_index: u64,
95
96    /// Index of the last key which was used by the other peer to encrypt a message towards us. We
97    /// keep it around to understand which secret keys we can remove.
98    our_min_key_index: u64,
99
100    /// List of all secret keys we generated ourselves. We sent the public counterpart to the other
101    /// peer.
102    our_secret_keys: HashMap<u64, SecretKey>,
103
104    /// Last secret key the other peer generated for us. This is part of the 2SM protocol and an
105    /// optimization where the remote end can _also_ generate secrets for us.
106    our_received_secret_key: Option<SecretKey>,
107
108    /// Which key we use to decrypt the next incoming message.
109    their_next_key_used: KeyUsed,
110
111    /// Key-material we need to encrypt the first message with the help of X3DH and prekeys.
112    their_prekey_bundle: Option<KB>,
113
114    /// Last known public key of the other peer. We use it to encrypt a message towards them.
115    their_verifying_key: Option<PublicKey>,
116}
117
118// Public methods.
119
120impl<KMG, KB> TwoParty<KMG, KB>
121where
122    KMG: IdentityManager<KMG::State> + PreKeyManager,
123    KB: KeyBundle,
124{
125    /// Initialise new 2SM state to send a message to this receiver for the first time using the
126    /// other party's pre-key bundle.
127    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    /// Initialise new 2SM state to receive a message from any sender for the first time.
140    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    /// Securely send a `plaintext` message to the other party.
153    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    /// Handle receiving a secure message from the other party.
188    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/// 2SM states indicating which key material was used.
206#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
207#[allow(clippy::enum_variant_names)]
208pub enum KeyUsed {
209    /// Previously published keys ("prekeys") for X3DH.
210    PreKey,
211
212    /// Key the receiving peer received last time from the sending peer for HPKE.
213    ReceivedKey,
214
215    /// Key the receiving peer generated themselves at some time. We can refer to the exact key by
216    /// it's index.
217    OwnKey(u64),
218}
219
220/// 2SM message to be sent over the network.
221///
222/// Note that this does not contain any additional information about the sender and receiver. This
223/// information needs to be added in applications.
224#[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    /// Message was encrypted using X3DH pre-keys (initial round).
233    PreKey(X3dhCiphertext),
234
235    /// Message was encrypted using HPKE.
236    Hpke(HpkeCiphertext),
237}
238
239/// Payload from sender which will be encrypted containing the actual message `plaintext` and
240/// meta-data we need for the 2SM protocol.
241#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
242pub struct TwoPartyPlaintext {
243    /// Secret message for the receiver.
244    plaintext: Vec<u8>,
245
246    /// Newly generated secret for the receiver, to be used in future 2SM rounds.
247    receiver_new_secret: SecretKey,
248
249    /// Newly generated public key of the sender, to be used in future 2SM rounds.
250    sender_new_verifying_key: PublicKey,
251
252    /// Index of the newly generated key of the sender, the receiver refers to it when using it in
253    /// future 2SM rounds.
254    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
267// Private methods.
268
269impl<KMG, KB> TwoParty<KMG, KB>
270where
271    KMG: IdentityManager<KMG::State> + PreKeyManager,
272    KB: KeyBundle,
273{
274    /// Encrypt a message toward the other party using X3DH when it is the first round or HPKE for
275    /// subsequent rounds.
276    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                // Establish secret via X3DH from prekey when no secret is given yet.
285                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    /// Decrypt a message from the other party using X3DH when it is the first round or HPKE for
307    /// subsequent rounds.
308    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                // If the underlying key manager provides a one-time secret, we use it here.
321                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                        // Fails when sender used an invalid / expired pre-key for initial X3DH.
336                        .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    /// Generate fresh key material for us and the other party for future 2SM rounds.
379    ///
380    /// This material is sent as part of the encrypted ciphertext, attached next to the actual
381    /// secret message. Each party prepares the received keys to be available for future rounds.
382    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        // Alice generates their key material.
462
463        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        // Bob generates their key material.
469
470        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        // Alice and Bob set up the 2SM protocol handlers for each other.
479
480        let alice_2sm = OneTimeTwoParty::init_to_send(bob_prekey_bundle);
481
482        // Alice doesn't have any secret HPKE keys yet and will use Bob's pre-keys for X3DH.
483        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        // Bob doesn't have any secret HPKE keys yet and will wait for Alice reaching out.
491        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        // They start exchanging "secret messages" to each other.
497
498        // 1. Alice sends a message to Bob using their pre-keys for X3DH.
499        let (alice_2sm, message_1) =
500            OneTimeTwoParty::send(alice_2sm, &alice_manager, b"Hello, Bob!", &rng).unwrap();
501
502        // Alice generated their own secret key and sends the public part to Bob for future rounds.
503        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        // Alice also generated the secret key for Bob, so Alice also knows their public key
508        // for the future already.
509        assert!(alice_2sm.their_verifying_key.is_some());
510
511        // Alice didn't receive anything from Bob yet.
512        assert!(alice_2sm.our_received_secret_key.is_none());
513
514        // In the future Alice would use the key they just generated to decrypt messages from Bob.
515        assert_eq!(alice_2sm.their_next_key_used, KeyUsed::ReceivedKey);
516
517        // Alice dropped the now-used pre-keys of Bob.
518        assert!(alice_2sm.their_prekey_bundle.is_none());
519
520        // 2. Bob receives Alice's message.
521        let (bob_2sm, bob_manager, receive_1) =
522            OneTimeTwoParty::receive(bob_2sm, bob_manager, message_1).unwrap();
523
524        // Bob still doesn't have any generated keys yet.
525        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        // Bob learned about the new public key (1) of Alice.
530        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        // Bob got their new secret key from Alice.
543        assert!(bob_2sm.our_received_secret_key.is_some());
544
545        // Bob would use Alice's new secret key for decrypting future messages.
546        assert_eq!(bob_2sm.their_next_key_used, KeyUsed::OwnKey(1));
547
548        // Bob still doesn't have Alice's pre-key bundle.
549        assert!(bob_2sm.their_prekey_bundle.is_none());
550
551        // 3. Alice sends another message to Bob and they receive it.
552        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        // Alice generated another secret and keeps now two of them around as Bob didn't reply yet.
558        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        // The secret keys are unique for each round.
563        assert_ne!(
564            alice_2sm.our_secret_keys.get(&1).unwrap(),
565            alice_2sm.our_secret_keys.get(&2).unwrap(),
566        );
567
568        // Bob learned about the new public key (2) of Alice.
569        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        // 4. Bob answers to Alice.
582        let (bob_2sm, message_3) =
583            OneTimeTwoParty::send(bob_2sm, &bob_manager, b"I'm alright. Thank you!", &rng).unwrap();
584
585        // Bob used Alice's latest public key (2) to encrypt this message.
586        assert_eq!(message_3.key_used, KeyUsed::OwnKey(2));
587
588        // Bob generated their own secret key and sends the public part to Alice for future rounds.
589        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        // Bob assumes now that Alice will use Bob's secret key for future messages.
594        assert_eq!(bob_2sm.their_next_key_used, KeyUsed::ReceivedKey);
595
596        // 5. Alice receives the message from Bob.
597        let (alice_2sm, alice_manager, receive_3) =
598            OneTimeTwoParty::receive(alice_2sm, alice_manager, message_3).unwrap();
599
600        // Alice removed the used secret key of this message (2) and all previous secrets as well
601        // (1) for forward secrecy.
602        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        // 6. Both parties continue chatting with each other ..
607        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        // Messages can be correctly decrypted.
618        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        // 7. They write a message to each other at the same time.
625        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        // Both Alice and Bob still only have one secret key and all other keys have been removed.
639        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        // Alice generates their long-term key material.
648
649        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        // Bob generates their long-term key material.
655
656        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        // Alice and Bob set up the 2SM protocol handlers for each other.
664
665        let alice_2sm_a = LongTermTwoParty::init_to_send(bob_prekey_bundle.clone());
666        let bob_2sm_a = LongTermTwoParty::init_to_receive();
667
668        // They start exchanging "secret messages" to each other in Group A.
669
670        let (alice_2sm_a, message_1) =
671            LongTermTwoParty::send(alice_2sm_a, &alice_manager, b"Hello, Bob!", &rng).unwrap();
672
673        // Public key of "Bob" for the first round in Group A.
674        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        // Sometime later they start another group B with the same long-term pre-keys.
688
689        let alice_2sm_b = LongTermTwoParty::init_to_send(bob_prekey_bundle);
690        let bob_2sm_b = LongTermTwoParty::init_to_receive();
691
692        // They start exchanging "secret messages" to each other.
693
694        let (alice_2sm_b, message_1) =
695            LongTermTwoParty::send(alice_2sm_b, &alice_manager, b"Hello, again, Bob!", &rng)
696                .unwrap();
697
698        // Public key of "Bob" for the first round in Group B.
699        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        // The keys for the first round should be different across groups.
713
714        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        // Alice generates their key material.
722
723        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        // Bob generates their key material.
729
730        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        // Alice and Bob set up the 2SM protocol handlers for each other.
739
740        let alice_2sm = OneTimeTwoParty::init_to_send(bob_prekey_bundle);
741        let bob_2sm = OneTimeTwoParty::init_to_receive();
742
743        // Alice sends a message to Bob.
744
745        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        // Bob receives the same message again.
751
752        let result = OneTimeTwoParty::receive(bob_2sm.clone(), bob_manager.clone(), message_1);
753        std::assert_matches!(result, Err(TwoPartyError::PreKeyReuse));
754
755        // Alice sends another message to Bob.
756
757        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        // Bob receives the same message again.
763
764        let result = OneTimeTwoParty::receive(bob_2sm, bob_manager, message_2);
765        std::assert_matches!(result, Err(TwoPartyError::Hpke(_)));
766    }
767}