ratchet_x2/
ratchet.rs

1use std::collections::VecDeque;
2#[cfg(feature = "std")]
3use std::marker::PhantomData;
4
5#[cfg(not(feature = "std"))]
6use alloc::collections::BTreeMap;
7use cryptimitives::key::x25519_ristretto;
8
9#[cfg(not(feature = "std"))]
10use core::marker::PhantomData;
11
12#[cfg(feature = "serde_derive")]
13use serde::{Deserialize, Serialize};
14
15use cryptraits::{
16    aead::Aead,
17    convert::{Len, ToVec},
18    hmac::Hmac,
19    kdf::Kdf,
20    key::{Generate, KeyPair, PublicKey, SecretKey},
21    key_exchange::DiffieHellman,
22};
23use rand_core::{CryptoRng, RngCore};
24
25use crate::errors::{DoubleRatchetError, DoubleRatchetResult};
26
27pub type Secret = [u8; 32];
28
29pub const DEFAULT_MAX_SKIP: usize = 2000;
30
31pub struct DoubleRatchetOptions {
32    pub max_skip: usize,
33}
34
35impl Default for DoubleRatchetOptions {
36    fn default() -> Self {
37        Self {
38            max_skip: DEFAULT_MAX_SKIP,
39        }
40    }
41}
42
43#[cfg(not(feature = "serde_derive"))]
44trait DrPkToVec: ToVec {}
45
46#[cfg(feature = "serde_derive")]
47pub trait DrPkToVec: ToVec + Serialize + for<'a> Deserialize<'a> {}
48
49#[cfg(feature = "serde_derive")]
50impl DrPkToVec for x25519_ristretto::PublicKey {}
51
52#[cfg(not(feature = "serde_derive"))]
53pub struct DoubleRatchet<K, KDF, AEAD, HMAC>
54where
55    K: KeyPair + DiffieHellman,
56    KDF: Kdf,
57    AEAD: Aead,
58    HMAC: Hmac,
59    <K as DiffieHellman>::SSK: ToVec,
60    <K as DiffieHellman>::PK: DrPkToVec,
61{
62    /// DH Ratchet key pair (the "sending" or "self" ratchet key)
63    dhs: K,
64
65    /// DH Ratchet public key (the "received" or "remote" key)
66    dhr: Option<K::PK>,
67
68    /// 32-byte Root Key
69    rk: Secret,
70
71    /// 32-byte Chain Key for sending
72    cks: Option<Secret>,
73
74    /// 32-byte Chain Key for receiving
75    ckr: Option<Secret>,
76
77    /// Message number for sending
78    ns: u32,
79
80    /// Message number for receiving
81    nr: u32,
82
83    /// Number of messages in previous sending chain
84    pn: u32,
85
86    /// Dictionary of skipped-over message keys, indexed by ratchet public key and message number.
87    mkskipped: VecDeque<(Vec<u8>, u32, Secret)>,
88
89    /// Max number of skipped-over message keys in storage.
90    max_skipped: usize,
91
92    _kdf: PhantomData<KDF>,
93    _aead: PhantomData<AEAD>,
94    _hmac: PhantomData<HMAC>,
95}
96
97#[cfg(feature = "serde_derive")]
98#[derive(Serialize, Deserialize)]
99pub struct DoubleRatchet<K, KDF, AEAD, HMAC>
100where
101    K: KeyPair + DiffieHellman,
102    KDF: Kdf,
103    AEAD: Aead,
104    HMAC: Hmac,
105    <K as DiffieHellman>::SSK: ToVec,
106    <K as DiffieHellman>::PK: DrPkToVec,
107{
108    /// DH Ratchet key pair (the "sending" or "self" ratchet key)
109    dhs: K,
110
111    /// DH Ratchet public key (the "received" or "remote" key)
112    dhr: Option<K::PK>,
113
114    /// 32-byte Root Key
115    rk: Secret,
116
117    /// 32-byte Chain Key for sending
118    cks: Option<Secret>,
119
120    /// 32-byte Chain Key for receiving
121    ckr: Option<Secret>,
122
123    /// Message number for sending
124    ns: u32,
125
126    /// Message number for receiving
127    nr: u32,
128
129    /// Number of messages in previous sending chain
130    pn: u32,
131
132    /// Dictionary of skipped-over message keys, indexed by ratchet public key and message number.
133    mkskipped: VecDeque<(Vec<u8>, u32, Secret)>,
134
135    /// Max number of skipped-over message keys in storage.
136    max_skipped: usize,
137
138    #[serde(skip_serializing, skip_deserializing)]
139    _kdf: PhantomData<KDF>,
140
141    #[serde(skip_serializing, skip_deserializing)]
142    _aead: PhantomData<AEAD>,
143
144    #[serde(skip_serializing, skip_deserializing)]
145    _hmac: PhantomData<HMAC>,
146}
147
148/// Double Ratchet message header.
149#[derive(Debug, Clone, PartialEq)]
150#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
151pub struct Header<PK: PublicKey> {
152    /// DH Ratchet key (the "sending" or "self" ratchet key)
153    dhs: PK,
154
155    /// Number of messages in previous sending chain
156    pn: u32,
157
158    /// Message number
159    n: u32,
160}
161
162impl<PK: PublicKey> Header<PK> {
163    pub fn dhs(&self) -> &PK {
164        &self.dhs
165    }
166
167    pub fn pn(&self) -> u32 {
168        self.pn
169    }
170
171    pub fn n(&self) -> u32 {
172        self.n
173    }
174}
175
176impl<PK: PublicKey + ToVec> ToVec for Header<PK> {
177    fn to_vec(&self) -> Vec<u8>
178    where
179        Self: Sized,
180    {
181        let mut v = Vec::new();
182        v.extend_from_slice(&self.dhs.to_vec());
183        v.extend_from_slice(&self.pn.to_be_bytes());
184        v.extend_from_slice(&self.n.to_be_bytes());
185        v
186    }
187}
188
189impl<PK: PublicKey + Len> Len for Header<PK> {
190    const LEN: usize = PK::LEN + 8;
191}
192
193impl<'a, K, KDF, AEAD, HMAC> DoubleRatchet<K, KDF, AEAD, HMAC>
194where
195    K: KeyPair + DiffieHellman + Generate,
196    KDF: Kdf,
197    AEAD: Aead,
198    HMAC: Hmac,
199    <K as DiffieHellman>::SSK: ToVec,
200    <K as DiffieHellman>::PK: DrPkToVec,
201{
202    /// Initialize "Alice": the sender of the first message.
203    pub fn init_alice<R>(
204        ssk: &impl ToVec,
205        bob_dh_pk: K::PK,
206        ckr: Option<Secret>,
207        csprng: &mut R,
208    ) -> DoubleRatchet<K, KDF, AEAD, HMAC>
209    where
210        R: CryptoRng + RngCore,
211        K::SSK: ToVec,
212    {
213        Self::do_init_alice(
214            ssk,
215            bob_dh_pk,
216            ckr,
217            &DoubleRatchetOptions::default(),
218            csprng,
219        )
220    }
221
222    /// Initialize "Alice": the sender of the first message, with custom options.
223    pub fn init_alice_with_options<R>(
224        ssk: &impl ToVec,
225        bob_dh_pk: K::PK,
226        ckr: Option<Secret>,
227        opts: &DoubleRatchetOptions,
228        csprng: &mut R,
229    ) -> DoubleRatchet<K, KDF, AEAD, HMAC>
230    where
231        R: CryptoRng + RngCore,
232        K::SSK: ToVec,
233    {
234        Self::do_init_alice(ssk, bob_dh_pk, ckr, opts, csprng)
235    }
236
237    pub fn do_init_alice<R>(
238        ssk: &impl ToVec,
239        bob_dh_pk: K::PK,
240        ckr: Option<Secret>,
241        opts: &DoubleRatchetOptions,
242        csprng: &mut R,
243    ) -> DoubleRatchet<K, KDF, AEAD, HMAC>
244    where
245        R: CryptoRng + RngCore,
246        K::SSK: ToVec,
247    {
248        let dhs = K::generate_with(csprng);
249        let (rk, cks) = Self::kdf_rk(
250            Some(&ssk.to_vec()),
251            b"WhisperText",
252            &dhs.diffie_hellman(&bob_dh_pk).to_vec(),
253        )
254        .unwrap();
255
256        Self {
257            dhs,
258            dhr: Some(bob_dh_pk),
259            rk,
260            cks: Some(cks),
261            ckr,
262            ns: 0,
263            nr: 0,
264            pn: 0,
265            mkskipped: Default::default(),
266            max_skipped: opts.max_skip,
267            _kdf: PhantomData::default(),
268            _aead: PhantomData::default(),
269            _hmac: PhantomData::default(),
270        }
271    }
272
273    /// Initialize "Bob": the receiver of the first message.
274    pub fn init_bob(rk: &impl ToVec, dhs: K, cks: Option<Secret>) -> Self {
275        Self::do_init_bob(rk, dhs, cks, &DoubleRatchetOptions::default())
276    }
277
278    /// Initialize "Bob": the receiver of the first message, with custom options.
279    pub fn init_bob_with_options(
280        rk: &impl ToVec,
281        dhs: K,
282        cks: Option<Secret>,
283        opts: &DoubleRatchetOptions,
284    ) -> Self {
285        Self::do_init_bob(rk, dhs, cks, opts)
286    }
287
288    pub fn do_init_bob(
289        rk: &impl ToVec,
290        dhs: K,
291        cks: Option<Secret>,
292        opts: &DoubleRatchetOptions,
293    ) -> Self {
294        Self {
295            dhs,
296            dhr: None,
297            rk: rk.to_vec().try_into().unwrap(),
298            cks,
299            ckr: None,
300            ns: 0,
301            nr: 0,
302            pn: 0,
303            mkskipped: Default::default(),
304            max_skipped: opts.max_skip,
305            _kdf: PhantomData::default(),
306            _aead: PhantomData::default(),
307            _hmac: PhantomData::default(),
308        }
309    }
310
311    pub fn encrypt<R>(
312        &mut self,
313        data: &[u8],
314        aad: &[u8],
315        csprng: &mut R,
316    ) -> (Header<<<K as KeyPair>::SK as SecretKey>::PK>, Vec<u8>)
317    where
318        R: CryptoRng + RngCore,
319    {
320        self.try_encrypt(data, aad, csprng).unwrap()
321    }
322
323    pub fn try_encrypt<R>(
324        &mut self,
325        data: &[u8],
326        aad: &[u8],
327        csprng: &mut R,
328    ) -> DoubleRatchetResult<(Header<<<K as KeyPair>::SK as SecretKey>::PK>, Vec<u8>)>
329    where
330        R: CryptoRng + RngCore,
331    {
332        if let Some(dhr) = self.dhr {
333            if self.cks.is_none() {
334                self.dhs = K::generate_with(csprng);
335                let (rk, cks) = Self::kdf_rk(
336                    Some(&self.dhs.diffie_hellman(&dhr).to_vec()),
337                    b"WhisperText",
338                    &self.rk,
339                )
340                .unwrap();
341
342                self.rk = rk;
343                self.cks = Some(cks);
344                self.pn = self.ns;
345                self.ns = 0;
346            }
347        } else {
348            return Err(DoubleRatchetError::NotInitialized);
349        }
350
351        let (new_cks, mk) = Self::kdf_ck(&self.cks.unwrap()).unwrap();
352        self.cks = Some(new_cks);
353
354        let header = self.header();
355
356        let mut nonce = vec![0u8; 8];
357        nonce.extend_from_slice(&self.ns.to_be_bytes());
358
359        self.ns += 1;
360
361        Ok((
362            header,
363            AEAD::new(&mk).encrypt(&nonce, data, Some(aad)).unwrap(),
364        ))
365    }
366
367    fn kdf_rk(salt: Option<&[u8]>, info: &[u8], input: &[u8]) -> Result<(Secret, Secret), KDF::E> {
368        let mut output = [0u8; 64];
369
370        KDF::new(salt, input).expand(info, &mut output)?;
371
372        let (root_key, chain_key) = output.split_at(32);
373
374        Ok((root_key.try_into().unwrap(), chain_key.try_into().unwrap()))
375    }
376
377    fn kdf_ck(key: &[u8]) -> Result<(Secret, Secret), HMAC::E> {
378        let mut mac = HMAC::new_from_slice(key)?;
379        mac.update(&[0x01]);
380        let ck = mac.finalize();
381
382        let mut mac = HMAC::new_from_slice(key)?;
383        mac.update(&[0x02]);
384        let mk = mac.finalize();
385
386        Ok((ck.try_into().unwrap(), mk.try_into().unwrap()))
387    }
388
389    fn header(&self) -> Header<<<K as KeyPair>::SK as SecretKey>::PK> {
390        Header {
391            dhs: self.dhs.to_public(),
392            pn: self.pn,
393            n: self.ns,
394        }
395    }
396
397    pub fn decrypt<R>(
398        &mut self,
399        header: &Header<K::PK>,
400        ciphertext: &[u8],
401        aad: &[u8],
402        csprng: &mut R,
403    ) -> Vec<u8>
404    where
405        R: CryptoRng + RngCore,
406    {
407        self.try_decrypt(header, ciphertext, aad, csprng).unwrap()
408    }
409
410    pub fn try_decrypt<R>(
411        &mut self,
412        header: &Header<K::PK>,
413        ciphertext: &[u8],
414        aad: &[u8],
415        csprng: &mut R,
416    ) -> DoubleRatchetResult<Vec<u8>>
417    where
418        R: CryptoRng + RngCore,
419    {
420        let mut nonce = vec![0u8; 8];
421        nonce.extend_from_slice(&header.n.to_be_bytes());
422
423        if let Some(mk) = self.get_skipped_message_key(header.dhs, header.n) {
424            return AEAD::new(&mk)
425                .decrypt(&nonce, ciphertext, Some(aad))
426                .or(Err(DoubleRatchetError::AeadError));
427        }
428
429        if Some(&header.dhs) != self.dhr.as_ref() {
430            self.skip_message_keys(header.pn)?;
431            self.dh_ratchet(header, csprng)
432        }
433
434        self.skip_message_keys(header.n)?;
435
436        let (ckr, mk) = Self::kdf_ck(&self.ckr.unwrap()).unwrap();
437        self.ckr = Some(ckr);
438        self.nr += 1;
439
440        AEAD::new(&mk)
441            .decrypt(&nonce, ciphertext, Some(aad))
442            .or(Err(DoubleRatchetError::AeadError))
443    }
444
445    fn dh_ratchet<R>(&mut self, header: &Header<K::PK>, csprng: &mut R)
446    where
447        R: CryptoRng + RngCore,
448    {
449        self.pn = self.ns;
450        self.ns = 0;
451        self.nr = 0;
452        self.dhr = Some(header.dhs);
453
454        let (rk, ckr) = Self::kdf_rk(
455            Some(&self.rk),
456            b"WhisperText",
457            &self.dhs.diffie_hellman(&self.dhr.unwrap()).to_vec(),
458        )
459        .unwrap();
460
461        self.rk = rk;
462        self.ckr = Some(ckr);
463        self.dhs = K::generate_with(csprng);
464
465        let (rk, cks) = Self::kdf_rk(
466            Some(&self.rk),
467            b"WhisperText",
468            &self.dhs.diffie_hellman(&self.dhr.unwrap()).to_vec(),
469        )
470        .unwrap();
471
472        self.rk = rk;
473        self.cks = Some(cks);
474    }
475
476    fn skip_message_keys(&mut self, until: u32) -> DoubleRatchetResult<()> {
477        while self.nr < until {
478            if self.mkskipped.len() >= self.max_skipped {
479                self.mkskipped.pop_front();
480            }
481
482            if let Some(ckr) = self.ckr {
483                let (ckr, mk) = Self::kdf_ck(&ckr).unwrap();
484                self.ckr = Some(ckr);
485                self.mkskipped
486                    .push_back((self.dhr.unwrap().to_vec(), self.nr, mk));
487                self.nr += 1;
488            }
489        }
490        Ok(())
491    }
492
493    fn get_skipped_message_key(&mut self, ratchet_key: impl ToVec, n: u32) -> Option<[u8; 32]> {
494        let pk = ratchet_key.to_vec();
495
496        self.mkskipped
497            .iter()
498            .position(|(skipped_pk, skipped_n, _)| skipped_pk == &pk && *skipped_n == n)
499            .and_then(|index| self.mkskipped.remove(index))
500            .map(|(_, _, mk)| mk)
501    }
502}
503
504#[cfg(all(test, feature = "cryptimitives"))]
505mod tests {
506    use cryptimitives::{aead, hmac, kdf, key::x25519_ristretto};
507    use rand_core::OsRng;
508
509    use super::*;
510
511    type DR = DoubleRatchet<
512        x25519_ristretto::KeyPair,
513        kdf::sha256::Kdf,
514        aead::aes_gcm::Aes256Gcm,
515        hmac::sha256::Hmac,
516    >;
517
518    fn asymmetric_setup<R>(opts: Option<DoubleRatchetOptions>, csprng: &mut R) -> (DR, DR)
519    where
520        R: CryptoRng + RngCore,
521    {
522        let alice_pair = x25519_ristretto::KeyPair::default();
523        let bob_pair = x25519_ristretto::KeyPair::default();
524
525        let ssk = alice_pair.diffie_hellman(bob_pair.public());
526
527        let opts = opts.unwrap_or_default();
528
529        let alice = DR::init_alice_with_options(&ssk, bob_pair.to_public(), None, &opts, csprng);
530        let bob = DR::init_bob_with_options(&ssk, bob_pair, None, &opts);
531
532        (alice, bob)
533    }
534
535    #[test]
536    fn test_asymmetric() {
537        let (mut alice, mut bob) = asymmetric_setup(None, &mut OsRng);
538
539        let (pt_a, ad_a) = (b"Hey, Bob", b"A2B");
540        let (pt_b, ad_b) = (b"Hey, Alice", b"B2A");
541
542        let (header_a, ciphertext_a) = alice.encrypt(pt_a, ad_a, &mut OsRng);
543
544        assert_eq!(
545            bob.try_encrypt(pt_b, ad_b, &mut OsRng),
546            Err(DoubleRatchetError::NotInitialized)
547        );
548
549        assert_eq!(
550            bob.decrypt(&header_a, &ciphertext_a, ad_a, &mut OsRng),
551            Vec::from(&pt_a[..])
552        );
553    }
554
555    #[test]
556    fn test_out_of_order() {
557        let (mut alice, mut bob) = asymmetric_setup(None, &mut OsRng);
558
559        let (ad_a, ad_b) = (b"A2B", b"B2A");
560        let pt_a_0 = b"Good day Robert";
561
562        let (h_a_0, ct_a_0) = alice.encrypt(pt_a_0, ad_a, &mut OsRng);
563
564        assert_eq!(
565            bob.decrypt(&h_a_0, &ct_a_0, ad_a, &mut OsRng),
566            Vec::from(&pt_a_0[..])
567        );
568
569        let pt_a_1 = b"Do you like Rust?";
570        let (h_a_1, ct_a_1) = alice.encrypt(pt_a_1, ad_a, &mut OsRng);
571
572        // Bob misses pt_a_1
573
574        let pt_b_0 = b"Salutations Allison";
575        let (h_b_0, ct_b_0) = bob.encrypt(pt_b_0, ad_b, &mut OsRng);
576
577        // Alice misses pt_b_0
578        let pt_b_1 = b"How is your day going?";
579        let (h_b_1, ct_b_1) = bob.encrypt(pt_b_1, ad_b, &mut OsRng);
580
581        assert_eq!(
582            alice.decrypt(&h_b_1, &ct_b_1, ad_b, &mut OsRng),
583            Vec::from(&pt_b_1[..])
584        );
585
586        let pt_a_2 = b"My day is fine.";
587        let (h_a_2, ct_a_2) = alice.encrypt(pt_a_2, ad_a, &mut OsRng);
588
589        let pt_a_3 = b"My day is not that fine...";
590        let (h_a_3, ct_a_3) = alice.encrypt(pt_a_3, ad_a, &mut OsRng);
591
592        let pt_a_4 = b"Its rainy";
593        let (h_a_4, ct_a_4) = alice.encrypt(pt_a_4, ad_a, &mut OsRng);
594
595        let pt_a_5 = b"And windy";
596        let (h_a_5, ct_a_5) = alice.encrypt(pt_a_5, ad_a, &mut OsRng);
597
598        let pt_a_6 = b"And muddy";
599        let (h_a_6, ct_a_6) = alice.encrypt(pt_a_6, ad_a, &mut OsRng);
600
601        assert_eq!(
602            bob.decrypt(&h_a_6, &ct_a_6, ad_a, &mut OsRng),
603            Vec::from(&pt_a_6[..])
604        );
605
606        assert_eq!(
607            bob.decrypt(&h_a_5, &ct_a_5, ad_a, &mut OsRng),
608            Vec::from(&pt_a_5[..])
609        );
610
611        assert_eq!(
612            bob.decrypt(&h_a_4, &ct_a_4, ad_a, &mut OsRng),
613            Vec::from(&pt_a_4[..])
614        );
615
616        assert_eq!(
617            bob.decrypt(&h_a_2, &ct_a_2, ad_a, &mut OsRng),
618            Vec::from(&pt_a_2[..])
619        );
620
621        assert_eq!(
622            bob.decrypt(&h_a_3, &ct_a_3, ad_a, &mut OsRng),
623            Vec::from(&pt_a_3[..])
624        );
625
626        // now Bob receives pt_a_1
627        assert_eq!(
628            bob.decrypt(&h_a_1, &ct_a_1, ad_a, &mut OsRng),
629            Vec::from(&pt_a_1[..])
630        );
631
632        let pt_b_2 = b"Yes, I like Rust";
633        let (h_b_2, ct_b_2) = bob.encrypt(pt_b_2, ad_b, &mut OsRng);
634
635        assert_eq!(
636            alice.decrypt(&h_b_2, &ct_b_2, ad_b, &mut OsRng),
637            Vec::from(&pt_b_2[..])
638        );
639
640        // now Alice receives pt_b_0
641        assert_eq!(
642            alice.decrypt(&h_b_0, &ct_b_0, ad_b, &mut OsRng),
643            Vec::from(&pt_b_0[..])
644        );
645    }
646
647    #[cfg(feature = "serde_derive")]
648    #[test]
649    fn test_asymmetric_serde() {
650        let (bob_serialized, header_a, ciphertext_a, ad_a, pt_a) = {
651            let (mut alice, mut bob) = asymmetric_setup(None, &mut OsRng);
652
653            let (pt_a, ad_a) = (b"Hey, Bob", b"A2B");
654            let (pt_b, ad_b) = (b"Hey, Alice", b"B2A");
655
656            let (header_a, ciphertext_a) = alice.encrypt(pt_a, ad_a, &mut OsRng);
657
658            assert_eq!(
659                bob.try_encrypt(pt_b, ad_b, &mut OsRng),
660                Err(DoubleRatchetError::NotInitialized)
661            );
662
663            (
664                serde_json::to_string(&bob).unwrap(),
665                header_a,
666                ciphertext_a,
667                ad_a,
668                pt_a,
669            )
670        };
671
672        let mut bob: DR = serde_json::from_str(&bob_serialized).unwrap();
673
674        assert_eq!(
675            bob.decrypt(&header_a, &ciphertext_a, ad_a, &mut OsRng),
676            Vec::from(&pt_a[..])
677        );
678    }
679
680    #[cfg(feature = "serde_derive")]
681    #[test]
682    fn test_out_of_order_serde() {
683        let (mut alice, mut bob) = asymmetric_setup(None, &mut OsRng);
684
685        let (ad_a, ad_b) = (b"A2B", b"B2A");
686        let pt_a_0 = b"Good day Robert";
687
688        let (h_a_0, ct_a_0) = alice.encrypt(pt_a_0, ad_a, &mut OsRng);
689
690        assert_eq!(
691            bob.decrypt(&h_a_0, &ct_a_0, ad_a, &mut OsRng),
692            Vec::from(&pt_a_0[..])
693        );
694
695        let pt_a_1 = b"Do you like Rust?";
696        let (h_a_1, ct_a_1) = alice.encrypt(pt_a_1, ad_a, &mut OsRng);
697
698        // Bob misses pt_a_1
699
700        let pt_b_0 = b"Salutations Allison";
701        let (h_b_0, ct_b_0) = bob.encrypt(pt_b_0, ad_b, &mut OsRng);
702
703        // Alice misses pt_b_0
704        let pt_b_1 = b"How is your day going?";
705        let (h_b_1, ct_b_1) = bob.encrypt(pt_b_1, ad_b, &mut OsRng);
706
707        assert_eq!(
708            alice.decrypt(&h_b_1, &ct_b_1, ad_b, &mut OsRng),
709            Vec::from(&pt_b_1[..])
710        );
711
712        let pt_a_2 = b"My day is fine.";
713        let (h_a_2, ct_a_2) = alice.encrypt(pt_a_2, ad_a, &mut OsRng);
714
715        assert_eq!(
716            bob.decrypt(&h_a_2, &ct_a_2, ad_a, &mut OsRng),
717            Vec::from(&pt_a_2[..])
718        );
719
720        let bob_serialized = serde_json::to_string(&bob).unwrap();
721
722        let mut bob: DR = serde_json::from_str(&bob_serialized).unwrap();
723
724        // now Bob receives pt_a_1
725        assert_eq!(
726            bob.decrypt(&h_a_1, &ct_a_1, ad_a, &mut OsRng),
727            Vec::from(&pt_a_1[..])
728        );
729
730        let pt_b_2 = b"Yes, I like Rust";
731        let (h_b_2, ct_b_2) = bob.encrypt(pt_b_2, ad_b, &mut OsRng);
732
733        assert_eq!(
734            alice.decrypt(&h_b_2, &ct_b_2, ad_b, &mut OsRng),
735            Vec::from(&pt_b_2[..])
736        );
737
738        // now Alice receives pt_b_0
739        assert_eq!(
740            alice.decrypt(&h_b_0, &ct_b_0, ad_b, &mut OsRng),
741            Vec::from(&pt_b_0[..])
742        );
743    }
744
745    #[test]
746    fn test_max_keys() {
747        let (mut alice, mut bob) =
748            asymmetric_setup(Some(DoubleRatchetOptions { max_skip: 5 }), &mut OsRng);
749
750        let (pt_a, ad_a) = (b"Hey, Bob", b"A2B");
751
752        let (mut header_a, mut ciphertext_a) = alice.encrypt(pt_a, ad_a, &mut OsRng);
753
754        for _ in 0..=DEFAULT_MAX_SKIP {
755            (header_a, ciphertext_a) = alice.encrypt(pt_a, ad_a, &mut OsRng);
756        }
757
758        assert_eq!(
759            bob.decrypt(&header_a, &ciphertext_a, ad_a, &mut OsRng),
760            Vec::from(&pt_a[..])
761        );
762    }
763}