From 7bb3e95799e393e8c9e42d02ce30cb9cc7a65411 Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 14 May 2021 17:38:39 +0200 Subject: [PATCH] Added encrypted header and added nonce --- Cargo.toml | 2 +- src/aead.rs | 20 +++--- src/header.rs | 38 ++++++++-- src/kdf_root.rs | 14 ++++ src/lib.rs | 27 ++++---- src/ratchet.rs | 179 +++++++++++++++++++++++++++++++++++++++++++++--- tests/mod.rs | 106 ++++++++++++++++++++++++---- 7 files changed, 337 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c14e28f..4bc0b04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ homepage = "https://github.com/Decentrailzed-Communication-System/double-ratchet repository = "https://github.com/Decentrailzed-Communication-System/double-ratchet-2" readme = "README.md" keywords = ["double-ratchet", "crypto", "cryptography", "signal"] -version = "0.1.3" +version = "0.2.0" edition = "2018" license = "MIT" license-file = "LICENSE" diff --git a/src/aead.rs b/src/aead.rs index 8abdac9..5fa0123 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -1,30 +1,32 @@ use aes_gcm_siv::{Key, Aes256GcmSiv, Nonce}; use aes_gcm_siv::aead::{NewAead, AeadInPlace}; use alloc::vec::Vec; +use rand_core::{OsRng, RngCore}; const CONSTANT_NONCE: &[u8] = b"Super Noncel"; -pub fn encrypt(mk: &[u8; 32], plaintext: &[u8], associated_data: &[u8]) -> Vec { +pub fn encrypt(mk: &[u8; 32], plaintext: &[u8], associated_data: &[u8]) -> (Vec, [u8; 12]) { let key = Key::from_slice(mk); let cipher = Aes256GcmSiv::new(key); - - let nonce = Nonce::from_slice(&CONSTANT_NONCE); + let mut nonce_data = [0_u8; 12]; + OsRng::fill_bytes(&mut OsRng, &mut nonce_data); + let nonce = Nonce::from_slice(&nonce_data); let mut buffer = Vec::new(); buffer.extend_from_slice(plaintext); cipher.encrypt_in_place(nonce, associated_data, &mut buffer) .expect("Encryption failed"); - buffer + (buffer, nonce_data) } -pub fn decrypt(mk: &[u8; 32], ciphertext: &[u8], associated_data: &[u8]) -> Vec { +pub fn decrypt(mk: &[u8; 32], ciphertext: &[u8], associated_data: &[u8], nonce: &[u8; 12]) -> Vec { let key = Key::from_slice(mk); let cipher = Aes256GcmSiv::new(key); - let nonce = Nonce::from_slice(&CONSTANT_NONCE); + let nonce = Nonce::from_slice(nonce); let mut buffer = Vec::new(); buffer.extend_from_slice(ciphertext); - cipher.decrypt_in_place(nonce, associated_data, &mut buffer).expect("Decryption failure"); + cipher.decrypt_in_place(nonce, associated_data, &mut buffer).expect("Decryption failure {}"); buffer } @@ -38,8 +40,8 @@ mod tests { let test_data = include_bytes!("aead.rs").to_vec(); let associated_data = include_bytes!("lib.rs").to_vec(); let mk = gen_mk(); - let ciphertext = encrypt(&mk, &test_data, &associated_data); - let plaintext = decrypt(&mk, &ciphertext, &associated_data); + let (ciphertext, nonce) = encrypt(&mk, &test_data, &associated_data); + let plaintext = decrypt(&mk, &ciphertext, &associated_data, &nonce); assert_eq!(test_data, plaintext) } } \ No newline at end of file diff --git a/src/header.rs b/src/header.rs index 46ad285..af834d3 100644 --- a/src/header.rs +++ b/src/header.rs @@ -2,6 +2,9 @@ use x25519_dalek::PublicKey; use crate::dh::DhKeyPair; use alloc::vec::Vec; use serde::{Serialize, Deserialize}; +use crate::aead::encrypt; +use aes_gcm_siv::{Key, Nonce, Aes256GcmSiv}; +use aes_gcm_siv::aead::{NewAead, AeadInPlace, Error}; #[cfg(test)] use crate::dh::gen_key_pair; @@ -22,7 +25,7 @@ struct ExHeader { // Message Header impl Header { - #[doc(hidden)] + // #[doc(hidden)] pub fn new(dh_pair: &DhKeyPair, pn: usize, n: usize) -> Self { Header { public_key: dh_pair.public_key, @@ -30,7 +33,7 @@ impl Header { n, } } - #[doc(hidden)] + // #[doc(hidden)] pub fn concat(&self) -> Vec { let ex_header = ExHeader{ public_key: self.public_key.to_bytes(), @@ -39,6 +42,33 @@ impl Header { }; bincode::serialize(&ex_header).expect("Failed to serialize Header") } + + pub fn encrypt(&self, hk: &[u8; 32]) -> (Vec, [u8; 12]) { + let header_data = self.concat(); + encrypt(hk, &header_data, b"") + } + + pub fn decrypt(hk: &Option<[u8; 32]>, ciphertext: &[u8], nonce: &[u8; 12]) -> Option { + let key_d = match hk { + None => { + return None + }, + Some(d) => d + }; + let key = Key::from_slice(key_d); + let cipher = Aes256GcmSiv::new(key); + + let nonce = Nonce::from_slice(nonce); + let mut buffer = Vec::new(); + buffer.extend_from_slice(ciphertext); + match cipher.decrypt_in_place(nonce, b"", &mut buffer) { + Ok(_) => {} + Err(_) => { + return None + } + }; + Some(Header::from(buffer)) + } } impl From> for Header { @@ -108,8 +138,8 @@ mod tests { let mk = gen_mk(); let header_data = header.concat(); let data = include_bytes!("aead.rs"); - let encrypted = encrypt(&mk, data, &header_data); - let decrypted = decrypt(&mk, &encrypted, &header_data); + let (encrypted, nonce) = encrypt(&mk, data, &header_data); + let decrypted = decrypt(&mk, &encrypted, &header_data, &nonce); assert_eq!(decrypted, data.to_vec()) } } \ No newline at end of file diff --git a/src/kdf_root.rs b/src/kdf_root.rs index 2f75b98..6e4f731 100644 --- a/src/kdf_root.rs +++ b/src/kdf_root.rs @@ -24,6 +24,20 @@ pub fn kdf_rk(rk: &[u8; 32], dh_out: &SharedSecret) -> ([u8; 32], [u8; 32]) { .expect("Incorrect length")) } +pub fn kdf_rk_he(rk: &[u8; 32], dh_out: &SharedSecret) -> ([u8; 32], [u8; 32], [u8; 32]) { + let h = Hkdf::::new(Some(rk), dh_out.as_bytes()); + let mut okm = [0u8; 96]; + let info = b"Root Key Generator"; + h.expand(info, &mut okm).unwrap(); + let (rk, a) = okm.split_at(32); + let (ck, nhk) = a.split_at(32); + ( + rk.try_into().expect("Wrong length"), + ck.try_into().expect("Wrong length"), + nhk.try_into().expect("Wrong length") + ) +} + #[cfg(test)] pub fn gen_ck() -> [u8; 32] { let shared_secret = gen_shared_secret(); diff --git a/src/lib.rs b/src/lib.rs index d1b4b8e..724deba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,8 +18,8 @@ //! let mut alice_ratchet = Ratchet::init_alice(sk, public_key); // Creating Alice Ratchet with Bobs PublicKey //! let data = b"Hello World".to_vec(); // Data to be encrypted //! -//! let (header, encrypted) = alice_ratchet.ratchet_encrypt(&data); // Encrypting message with Alice Ratchet (Alice always needs to send the first message) -//! let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted); // Decrypt message with Bobs Ratchet +//! let (header, encrypted, nonce) = alice_ratchet.ratchet_encrypt(&data); // Encrypting message with Alice Ratchet (Alice always needs to send the first message) +//! let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted, &nonce); // Decrypt message with Bobs Ratchet //! assert_eq!(data, decrypted) //! ``` //! @@ -32,11 +32,11 @@ //! let mut alice_ratchet = Ratchet::init_alice(sk, public_key); // Creating Alice Ratchet with Bobs PublicKey //! let data = b"Hello World".to_vec(); // Data to be encrypted //! -//! let (header1, encrypted1) = alice_ratchet.ratchet_encrypt(&data); // Lost message -//! let (header2, encrypted2) = alice_ratchet.ratchet_encrypt(&data); // Successful message +//! let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data); // Lost message +//! let (header2, encrypted2, nonce2) = alice_ratchet.ratchet_encrypt(&data); // Successful message //! -//! let decrypted2 = bob_ratchet.ratchet_decrypt(&header2, &encrypted2); // Decrypting second message first -//! let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1); // Decrypting latter message +//! let decrypted2 = bob_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2); // Decrypting second message first +//! let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1); // Decrypting latter message //! //! let comp = decrypted1 == data && decrypted2 == data; //! assert!(comp); @@ -51,7 +51,7 @@ //! let (mut bob_ratchet, _) = Ratchet::init_bob(sk); //! let data = b"Hello World".to_vec(); //! -//! let (_, _) = bob_ratchet.ratchet_encrypt(&data); +//! let (_, _, _) = bob_ratchet.ratchet_encrypt(&data); //! ``` //! //! ## Encryption after recieving initial message @@ -66,11 +66,11 @@ //! //! let data = b"Hello World".to_vec(); //! -//! let (header1, encrypted1) = alice_ratchet.ratchet_encrypt(&data); -//! let _decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1); +//! let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data); +//! let _decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1); //! -//! let (header2, encrypted2) = bob_ratchet.ratchet_encrypt(&data); -//! let decrypted2 = alice_ratchet.ratchet_decrypt(&header2, &encrypted2); +//! let (header2, encrypted2, nonce2) = bob_ratchet.ratchet_encrypt(&data); +//! let decrypted2 = alice_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2); //! //! assert_eq!(data, decrypted2); //! ``` @@ -83,7 +83,7 @@ //! # let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk); //! # let mut alice_ratchet = Ratchet::init_alice(sk, public_key); //! # let data = b"hello World".to_vec(); -//! # let (header, _) = alice_ratchet.ratchet_encrypt(&data); +//! # let (header, _, _) = alice_ratchet.ratchet_encrypt(&data); //! let header_bytes: Vec = header.clone().into(); //! let header_const = Header::from(header_bytes); //! assert_eq!(header, header_const); @@ -97,7 +97,7 @@ //! //! TODO: //! - [x] Standard Double Ratchet -//! - [ ] [Double Ratchet with encrypted headers][3] +//! - [x] [Double Ratchet with encrypted headers][3] //! //! [1]: https://signal.org/docs/specifications/doubleratchet/ //! [2]: https://signal.org/docs/specifications/doubleratchet/#recommended-cryptographic-algorithms @@ -115,7 +115,6 @@ mod dh; mod kdf_root; mod kdf_chain; -/// Providing essential functions pub mod ratchet; /// Message Header diff --git a/src/ratchet.rs b/src/ratchet.rs index c6226cd..2cd7e0c 100644 --- a/src/ratchet.rs +++ b/src/ratchet.rs @@ -1,7 +1,10 @@ +//! Encryption with encrypted Headers +//! + use crate::dh::DhKeyPair; use x25519_dalek::PublicKey; use hashbrown::HashMap; -use crate::kdf_root::kdf_rk; +use crate::kdf_root::{kdf_rk, kdf_rk_he}; use crate::header::Header; use alloc::vec::Vec; use crate::kdf_chain::kdf_ck; @@ -60,21 +63,21 @@ impl Ratchet { } /// Encrypt Plaintext with [Ratchet]. Returns Message [Header] and ciphertext. - pub fn ratchet_encrypt(&mut self, plaintext: &[u8]) -> (Header, Vec) { + pub fn ratchet_encrypt(&mut self, plaintext: &[u8]) -> (Header, Vec, [u8; 12]) { let (cks, mk) = kdf_ck(&self.cks.unwrap()); self.cks = Some(cks); let header = Header::new(&self.dhs, self.pn, self.ns); self.ns += 1; - let encrypted_data = encrypt(&mk, plaintext, &header.concat()); - (header, encrypted_data) + let (encrypted_data, nonce) = encrypt(&mk, plaintext, &header.concat()); + (header, encrypted_data, nonce) } - fn try_skipped_message_keys(&mut self, header: &Header, ciphertext: &[u8]) -> Option> { + fn try_skipped_message_keys(&mut self, header: &Header, ciphertext: &[u8], nonce: &[u8; 12]) -> Option> { if self.mkskipped.contains_key(&(header.public_key, header.n)) { let mk = *self.mkskipped.get(&(header.public_key, header.n)) .unwrap(); self.mkskipped.remove(&(header.public_key, header.n)).unwrap(); - Some(decrypt(&mk, ciphertext, &header.concat())) + Some(decrypt(&mk, ciphertext, &header.concat(), nonce)) } else { None } @@ -99,8 +102,8 @@ impl Ratchet { } /// Decrypt ciphertext with ratchet. Requires Header. Returns plaintext. - pub fn ratchet_decrypt(&mut self, header: &Header, ciphertext: &[u8]) -> Vec { - let plaintext = self.try_skipped_message_keys(header, ciphertext); + pub fn ratchet_decrypt(&mut self, header: &Header, ciphertext: &[u8], nonce: &[u8; 12]) -> Vec { + let plaintext = self.try_skipped_message_keys(header, ciphertext, nonce); match plaintext { Some(d) => d, None => { @@ -114,7 +117,7 @@ impl Ratchet { let (ckr, mk) = kdf_ck(&self.ckr.unwrap()); self.ckr = Some(ckr); self.nr += 1; - decrypt(&mk, ciphertext, &header.concat()) + decrypt(&mk, ciphertext, &header.concat(), nonce) } } } @@ -136,3 +139,161 @@ impl Ratchet { } } +pub struct RatchetEncHeader { + dhs: DhKeyPair, + dhr: Option, + rk: [u8; 32], + cks: Option<[u8; 32]>, + ckr: Option<[u8; 32]>, + ns: usize, + nr: usize, + pn: usize, + hks: Option<[u8; 32]>, + hkr: Option<[u8; 32]>, + nhks: Option<[u8; 32]>, + nhkr: Option<[u8; 32]>, + mkskipped: HashMap<(Option<[u8; 32]>, usize), [u8; 32]> +} + +impl RatchetEncHeader { + pub fn init_alice(sk: [u8; 32], + bob_dh_public_key: PublicKey, + shared_hka: [u8; 32], + shared_nhkb: [u8; 32]) -> Self { + let dhs = DhKeyPair::new(); + let (rk, cks, nhks) = kdf_rk_he(&sk, &dhs.key_agreement(&bob_dh_public_key)); + RatchetEncHeader { + dhs, + dhr: Some(bob_dh_public_key), + rk, + cks: Some(cks), + ckr: None, + ns: 0, + nr: 0, + pn: 0, + mkskipped: HashMap::new(), + hks: Some(shared_hka), + hkr: None, + nhkr: Some(shared_nhkb), + nhks: Some(nhks), + } + } + + pub fn init_bob(sk: [u8; 32], shared_hka: [u8; 32], shared_nhkb: [u8; 32]) -> (Self, PublicKey) { + let dhs = DhKeyPair::new(); + let public_key = dhs.public_key; + let ratchet = Self { + dhs, + dhr: None, + rk: sk, + cks: None, + ckr: None, + ns: 0, + nr: 0, + pn: 0, + mkskipped: HashMap::new(), + hks: None, + nhks: Some(shared_nhkb), + hkr: None, + nhkr: Some(shared_hka), + }; + (ratchet, public_key) + } + + pub fn ratchet_encrypt(&mut self, plaintext: &[u8]) -> ((Vec, [u8; 12]), Vec, [u8; 12]) { + let (cks, mk) = kdf_ck(&self.cks.unwrap()); + self.cks = Some(cks); + let header = Header::new(&self.dhs, self.pn, self.ns); + let enc_header = header.encrypt(&self.hks.unwrap()); + self.ns += 1; + let encrypted = encrypt(&mk, plaintext, &header.concat()); + (enc_header, encrypted.0, encrypted.1) + } + + fn try_skipped_message_keys(&mut self, enc_header: &(Vec, [u8; 12]), + ciphertext: &[u8], nonce: &[u8; 12]) -> Option> { + for ((hk, n), mk) in self.mkskipped.iter() { + let header = Header::decrypt(hk, &enc_header.0, &enc_header.1); + match header { + None => { continue }, + Some(h) => { + if h.n == *n { + let mk = mk.clone(); + self.mkskipped.remove(&(*hk, *n)); + return Some(decrypt(&mk, ciphertext, &h.concat(), nonce)) + } + } + } + } + None + } + + fn decrypt_header(&mut self, enc_header: &(Vec, [u8; 12])) -> Result<(Header, bool), &str> { + let header = Header::decrypt(&self.hkr, &enc_header.0, &enc_header.1); + match header { + Some(h) => { return Ok((h, false)) }, + None => {}, + } + let header = Header::decrypt(&self.nhkr, &enc_header.0, &enc_header.1); + match header { + Some(h) => Ok((h, true)), + None => Err("Header is unencryptable!") + } + } + + fn skip_message_keys(&mut self, until: usize) -> Result<(), &str> { + if self.nr + MAX_SKIP < until { + return Err("Skipping went wrong") + } + match self.ckr { + Some(d) => { + while self.nr < until { + let (ckr, mk) = kdf_ck(&d); + self.ckr = Some(ckr); + self.mkskipped.insert((self.hkr, self.nr), mk); + self.nr += 1 + } + } + None => {} + } + Ok(()) + } + + fn dhratchet(&mut self, header: &Header) { + self.pn = self.ns; + self.ns = 0; + self.nr = 0; + self.hks = self.nhks; + self.hkr = self.nhkr; + self.dhr = Some(header.public_key); + let (rk, ckr, nhkr) = kdf_rk_he(&self.rk, + &self.dhs.key_agreement(&self.dhr.unwrap())); + self.rk = rk; + self.ckr = Some(ckr); + self.nhkr = Some(nhkr); + self.dhs = DhKeyPair::new(); + let (rk, cks, nhks) = kdf_rk_he(&self.rk, + &self.dhs.key_agreement(&self.dhr.unwrap())); + self.rk = rk; + self.cks = Some(cks); + self.nhks = Some(nhks); + } + + pub fn ratchet_decrypt(&mut self, enc_header: &(Vec, [u8; 12]), ciphertext: &[u8], nonce: &[u8; 12]) -> Vec { + let plaintext = self.try_skipped_message_keys(enc_header, ciphertext, nonce); + match plaintext { + Some(d) => { return d }, + None => {} + }; + let (header, dh_ratchet) = self.decrypt_header(enc_header).unwrap(); + if dh_ratchet { + self.skip_message_keys(header.pn).unwrap(); + self.dhratchet(&header); + } + self.skip_message_keys(header.n).unwrap(); + let (ckr, mk) = kdf_ck(&self.ckr.unwrap()); + self.ckr = Some(ckr); + self.nr += 1; + decrypt(&mk, ciphertext, &header.concat(), nonce) + } +} \ No newline at end of file diff --git a/tests/mod.rs b/tests/mod.rs index 3dbd3db..62604ba 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -1,4 +1,4 @@ -use double_ratchet_2::ratchet::Ratchet; +use double_ratchet_2::ratchet::{Ratchet, RatchetEncHeader}; #[test] fn ratchet_init() { @@ -13,8 +13,8 @@ fn ratchet_enc_single() { let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk); let mut alice_ratchet = Ratchet::init_alice(sk, public_key); let data = include_bytes!("../src/header.rs").to_vec(); - let (header, encrypted) = alice_ratchet.ratchet_encrypt(&data); - let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted); + let (header, encrypted, nonce) = alice_ratchet.ratchet_encrypt(&data); + let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted, &nonce); assert_eq!(data, decrypted) } @@ -24,10 +24,10 @@ fn ratchet_enc_skip() { let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk); let mut alice_ratchet = Ratchet::init_alice(sk, public_key); let data = include_bytes!("../src/header.rs").to_vec(); - let (header1, encrypted1) = alice_ratchet.ratchet_encrypt(&data); - let (header2, encrypted2) = alice_ratchet.ratchet_encrypt(&data); - let decrypted2 = bob_ratchet.ratchet_decrypt(&header2, &encrypted2); - let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1); + let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data); + let (header2, encrypted2, nonce2) = alice_ratchet.ratchet_encrypt(&data); + let decrypted2 = bob_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2); + let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1); let comp_res = decrypted1 == data && decrypted2 == data; assert!(comp_res) } @@ -38,7 +38,7 @@ fn ratchet_panic_bob() { let sk = [1; 32]; let (mut bob_ratchet, _) = Ratchet::init_bob(sk); let data = include_bytes!("../src/header.rs").to_vec(); - let (_, _) = bob_ratchet.ratchet_encrypt(&data); + let (_, _, _) = bob_ratchet.ratchet_encrypt(&data); } #[test] @@ -47,10 +47,92 @@ fn ratchet_encryt_decrypt_four() { let data = include_bytes!("../src/dh.rs").to_vec(); let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk); let mut alice_ratchet = Ratchet::init_alice(sk, public_key); - let (header1, encrypted1) = alice_ratchet.ratchet_encrypt(&data); - let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1); - let (header2, encrypted2) = bob_ratchet.ratchet_encrypt(&data); - let decrypted2 = alice_ratchet.ratchet_decrypt(&header2, &encrypted2); + let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data); + let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1); + let (header2, encrypted2, nonce2) = bob_ratchet.ratchet_encrypt(&data); + let decrypted2 = alice_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2); + let comp_res = decrypted1 == data && decrypted2 == data; + assert!(comp_res) +} + +#[test] +fn ratchet_ench_init() { + let sk = [1; 32]; + let shared_hka = [2; 32]; + let shared_nhkb = [3; 32]; + let (_bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, + shared_hka, + shared_nhkb); + let _alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, + shared_hka, shared_nhkb); +} + +#[test] +fn ratchet_ench_enc_single() { + let sk = [1; 32]; + let shared_hka = [2; 32]; + let shared_nhkb = [3; 32]; + let (mut bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, + shared_hka, + shared_nhkb); + let mut alice_ratchet = RatchetEncHeader::init_alice(sk, + public_key, + shared_hka, + shared_nhkb); + let data = include_bytes!("../src/header.rs").to_vec(); + let (header, encrypted, nonce) = alice_ratchet.ratchet_encrypt(&data); + let decrypted = bob_ratchet.ratchet_decrypt(&header, &encrypted, &nonce); + assert_eq!(data, decrypted) +} + +#[test] +fn ratchet_ench_enc_skip() { + let sk = [1; 32]; + let shared_hka = [2; 32]; + let shared_nhkb = [3; 32]; + let (mut bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, + shared_hka, + shared_nhkb); + let mut alice_ratchet = RatchetEncHeader::init_alice(sk, + public_key, + shared_hka, + shared_nhkb); + let data = include_bytes!("../src/header.rs").to_vec(); + let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data); + let (header2, encrypted2, nonce2) = alice_ratchet.ratchet_encrypt(&data); + let decrypted2 = bob_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2); + let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1); + let comp_res = decrypted1 == data && decrypted2 == data; + assert!(comp_res) +} + +#[test] +#[should_panic] +fn ratchet_ench_panic_bob() { + let sk = [1; 32]; + let shared_hka = [2; 32]; + let shared_nhkb = [3; 32]; + let (mut bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, + shared_hka, + shared_nhkb); + let data = include_bytes!("../src/header.rs").to_vec(); + let (_, _, _) = bob_ratchet.ratchet_encrypt(&data); +} + +#[test] +fn ratchet_ench_decrypt_four() { + let sk = [1; 32]; + let shared_hka = [2; 32]; + let shared_nhkb = [3; 32]; + let (mut bob_ratchet, public_key) = RatchetEncHeader::init_bob(sk, + shared_hka, + shared_nhkb); + let mut alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, shared_hka, shared_nhkb); + let data = include_bytes!("../src/dh.rs").to_vec(); + let (header1, encrypted1, nonce1) = alice_ratchet.ratchet_encrypt(&data); + let decrypted1 = bob_ratchet.ratchet_decrypt(&header1, &encrypted1, &nonce1); + let (header2, encrypted2, nonce2) = bob_ratchet.ratchet_encrypt(&data); + let decrypted2 = alice_ratchet.ratchet_decrypt(&header2, &encrypted2, &nonce2); let comp_res = decrypted1 == data && decrypted2 == data; assert!(comp_res) } \ No newline at end of file