// // Copyright 2020 Signal Messenger, LLC. // SPDX-License-Identifier: AGPL-3.0-only // mod support; use futures_util::FutureExt; use libsignal_protocol::*; use rand::rngs::OsRng; use std::convert::TryFrom; use support::*; #[test] #[allow(clippy::eval_order_dependence)] fn test_basic_prekey_v3() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let bob_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; let pre_key_id = 31337; let signed_pre_key_id = 22; let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key signed_pre_key_id, // signed pre key id bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; assert!(alice_store .load_session(&bob_address, None) .await? .is_some()); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); let original_message = "L'homme est condamné à être libre"; let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; assert_eq!( outgoing_message.message_type(), CiphertextMessageType::PreKey ); let incoming_message = CiphertextMessage::PreKeySignalMessage( PreKeySignalMessage::try_from(outgoing_message.serialize())?, ); bob_store .save_pre_key( pre_key_id, &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), None, ) .await?; bob_store .save_signed_pre_key( signed_pre_key_id, &SignedPreKeyRecord::new( signed_pre_key_id, /*timestamp*/ 42, &bob_signed_pre_key_pair, &bob_signed_pre_key_signature, ), None, ) .await?; let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), original_message ); let bobs_response = "Who watches the watchers?"; assert!(bob_store .load_session(&alice_address, None) .await? .is_some()); let bobs_session_with_alice = bob_store .load_session(&alice_address, None) .await? .expect("session found"); assert_eq!(bobs_session_with_alice.session_version()?, 3); assert_eq!(bobs_session_with_alice.alice_base_key()?.len(), 32 + 1); let bob_outgoing = encrypt(&mut bob_store, &alice_address, bobs_response).await?; assert_eq!(bob_outgoing.message_type(), CiphertextMessageType::Whisper); let alice_decrypts = decrypt(&mut alice_store, &bob_address, &bob_outgoing).await?; assert_eq!( String::from_utf8(alice_decrypts).expect("valid utf8"), bobs_response ); run_interaction( &mut alice_store, &alice_address, &mut bob_store, &bob_address, ) .await?; let mut alice_store = support::test_in_memory_protocol_store()?; let bob_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; let pre_key_id = 31337; let signed_pre_key_id = 22; let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id + 1, bob_pre_key_pair.public_key)), // pre key, signed_pre_key_id + 1, bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; bob_store .save_pre_key( pre_key_id + 1, &PreKeyRecord::new(pre_key_id + 1, &bob_pre_key_pair), None, ) .await?; bob_store .save_signed_pre_key( signed_pre_key_id + 1, &SignedPreKeyRecord::new( signed_pre_key_id + 1, /*timestamp*/ 42, &bob_signed_pre_key_pair, &bob_signed_pre_key_signature, ), None, ) .await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; assert!(matches!( decrypt(&mut bob_store, &alice_address, &outgoing_message) .await .unwrap_err(), SignalProtocolError::UntrustedIdentity(a) if a == alice_address )); assert!( bob_store .save_identity( &alice_address, alice_store .get_identity_key_pair(None) .await? .identity_key(), None, ) .await? ); let decrypted = decrypt(&mut bob_store, &alice_address, &outgoing_message).await?; assert_eq!( String::from_utf8(decrypted).expect("valid utf8"), original_message ); // Sign pre-key with wrong key: let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key signed_pre_key_id, bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *alice_store .get_identity_key_pair(None) .await? .identity_key(), )?; assert!(process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await .is_err()); Ok(()) } .now_or_never() .expect("sync") } #[test] #[ignore = "slow to run locally"] #[allow(clippy::eval_order_dependence)] fn chain_jump_over_limit() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let bob_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; let pre_key_id = 31337; let signed_pre_key_id = 22; let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key signed_pre_key_id, // signed pre key id bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; bob_store .save_pre_key( pre_key_id, &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), None, ) .await?; bob_store .save_signed_pre_key( signed_pre_key_id, &SignedPreKeyRecord::new( signed_pre_key_id, /*timestamp*/ 42, &bob_signed_pre_key_pair, &bob_signed_pre_key_signature, ), None, ) .await?; // Same as library consts.rs pub const MAX_FORWARD_JUMPS: usize = 25_000; for _i in 0..(MAX_FORWARD_JUMPS + 1) { let _msg = encrypt( &mut alice_store, &bob_address, "Yet another message for you", ) .await?; } let too_far = encrypt(&mut alice_store, &bob_address, "Now you have gone too far").await?; assert!(decrypt(&mut bob_store, &alice_address, &too_far) .await .is_err()); Ok(()) } .now_or_never() .expect("sync") } #[test] #[ignore = "slow to run locally"] #[allow(clippy::eval_order_dependence)] fn chain_jump_over_limit_with_self() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let a1_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let a2_address = ProtocolAddress::new("+14151111111".to_owned(), 2); let mut a1_store = support::test_in_memory_protocol_store()?; let mut a2_store = a1_store.clone(); // same key! let a2_pre_key_pair = KeyPair::generate(&mut csprng); let a2_signed_pre_key_pair = KeyPair::generate(&mut csprng); let a2_signed_pre_key_public = a2_signed_pre_key_pair.public_key.serialize(); let a2_signed_pre_key_signature = a2_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&a2_signed_pre_key_public, &mut csprng)?; let pre_key_id = 31337; let signed_pre_key_id = 22; let a2_pre_key_bundle = PreKeyBundle::new( a2_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id, a2_pre_key_pair.public_key)), // pre key signed_pre_key_id, // signed pre key id a2_signed_pre_key_pair.public_key, a2_signed_pre_key_signature.to_vec(), *a2_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &a2_address, &mut a1_store.session_store, &mut a1_store.identity_store, &a2_pre_key_bundle, &mut csprng, None, ) .await?; a2_store .save_pre_key( pre_key_id, &PreKeyRecord::new(pre_key_id, &a2_pre_key_pair), None, ) .await?; a2_store .save_signed_pre_key( signed_pre_key_id, &SignedPreKeyRecord::new( signed_pre_key_id, /*timestamp*/ 42, &a2_signed_pre_key_pair, &a2_signed_pre_key_signature, ), None, ) .await?; // Same as library consts.rs pub const MAX_FORWARD_JUMPS: usize = 25_000; for _i in 0..(MAX_FORWARD_JUMPS + 1) { let _msg = encrypt( &mut a1_store, &a2_address, "Yet another message for youself", ) .await?; } let too_far = encrypt( &mut a1_store, &a2_address, "This is the song that never ends", ) .await?; let ptext = decrypt(&mut a2_store, &a1_address, &too_far).await?; assert_eq!( String::from_utf8(ptext).unwrap(), "This is the song that never ends" ); Ok(()) } .now_or_never() .expect("sync") } #[test] #[allow(clippy::eval_order_dependence)] fn test_bad_signed_pre_key_signature() -> Result<(), SignalProtocolError> { async { let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let bob_store = support::test_in_memory_protocol_store()?; let mut csprng = OsRng; let bob_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)? .to_vec(); let pre_key_id = 31337; let signed_pre_key_id = 22; for bit in 0..8 * bob_signed_pre_key_signature.len() { let mut bad_signature = bob_signed_pre_key_signature.clone(); bad_signature[bit / 8] ^= 0x01u8 << (bit % 8); let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, Some((pre_key_id, bob_pre_key_pair.public_key)), signed_pre_key_id, bob_signed_pre_key_pair.public_key, bad_signature, *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; assert!(process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await .is_err()); } // Finally check that the non-corrupted signature is accepted: let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, Some((pre_key_id, bob_pre_key_pair.public_key)), signed_pre_key_id, bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature, *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; Ok(()) } .now_or_never() .expect("sync") } // testRepeatBundleMessageV2 cannot be represented #[test] #[allow(clippy::eval_order_dependence)] fn repeat_bundle_message_v3() -> Result<(), SignalProtocolError> { async { let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let mut csprng = OsRng; let bob_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; let pre_key_id = 31337; let signed_pre_key_id = 22; let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key signed_pre_key_id, // signed pre key id bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; assert!(alice_store .load_session(&bob_address, None) .await? .is_some()); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); let original_message = "L'homme est condamné à être libre"; let outgoing_message1 = encrypt(&mut alice_store, &bob_address, original_message).await?; let outgoing_message2 = encrypt(&mut alice_store, &bob_address, original_message).await?; assert_eq!( outgoing_message1.message_type(), CiphertextMessageType::PreKey ); assert_eq!( outgoing_message2.message_type(), CiphertextMessageType::PreKey ); let incoming_message = CiphertextMessage::PreKeySignalMessage( PreKeySignalMessage::try_from(outgoing_message1.serialize())?, ); bob_store .save_pre_key( pre_key_id, &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), None, ) .await?; bob_store .save_signed_pre_key( signed_pre_key_id, &SignedPreKeyRecord::new( signed_pre_key_id, /*timestamp*/ 42, &bob_signed_pre_key_pair, &bob_signed_pre_key_signature, ), None, ) .await?; let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), original_message ); let bob_outgoing = encrypt(&mut bob_store, &alice_address, original_message).await?; assert_eq!(bob_outgoing.message_type(), CiphertextMessageType::Whisper); let alice_decrypts = decrypt(&mut alice_store, &bob_address, &bob_outgoing).await?; assert_eq!( String::from_utf8(alice_decrypts).expect("valid utf8"), original_message ); // The test let incoming_message2 = CiphertextMessage::PreKeySignalMessage( PreKeySignalMessage::try_from(outgoing_message2.serialize())?, ); let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message2).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), original_message ); let bob_outgoing = encrypt(&mut bob_store, &alice_address, original_message).await?; let alice_decrypts = decrypt(&mut alice_store, &bob_address, &bob_outgoing).await?; assert_eq!( String::from_utf8(alice_decrypts).expect("valid utf8"), original_message ); Ok(()) } .now_or_never() .expect("sync") } #[test] #[allow(clippy::eval_order_dependence)] fn bad_message_bundle() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let bob_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; let pre_key_id = 31337; let signed_pre_key_id = 22; let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id Some((pre_key_id, bob_pre_key_pair.public_key)), signed_pre_key_id, // signed pre key id bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; bob_store .save_pre_key( pre_key_id, &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), None, ) .await?; bob_store .save_signed_pre_key( signed_pre_key_id, &SignedPreKeyRecord::new( signed_pre_key_id, /*timestamp*/ 42, &bob_signed_pre_key_pair, &bob_signed_pre_key_signature, ), None, ) .await?; assert!(alice_store .load_session(&bob_address, None) .await? .is_some()); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); let original_message = "L'homme est condamné à être libre"; assert!(bob_store.get_pre_key(pre_key_id, None).await.is_ok()); let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; assert_eq!( outgoing_message.message_type(), CiphertextMessageType::PreKey ); let outgoing_message = outgoing_message.serialize().to_vec(); let mut corrupted_message: Vec = outgoing_message.clone(); corrupted_message[outgoing_message.len() - 10] ^= 1; let incoming_message = CiphertextMessage::PreKeySignalMessage( PreKeySignalMessage::try_from(corrupted_message.as_slice())?, ); assert!(decrypt(&mut bob_store, &alice_address, &incoming_message) .await .is_err()); assert!(bob_store.get_pre_key(pre_key_id, None).await.is_ok()); let incoming_message = CiphertextMessage::PreKeySignalMessage( PreKeySignalMessage::try_from(outgoing_message.as_slice())?, ); let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), original_message ); assert!(matches!( bob_store.get_pre_key(pre_key_id, None).await.unwrap_err(), SignalProtocolError::InvalidPreKeyId )); Ok(()) } .now_or_never() .expect("sync") } #[test] #[allow(clippy::eval_order_dependence)] fn optional_one_time_prekey() -> Result<(), SignalProtocolError> { async { let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let mut csprng = OsRng; let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); let bob_signed_pre_key_signature = bob_store .get_identity_key_pair(None) .await? .private_key() .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; let signed_pre_key_id = 22; let bob_pre_key_bundle = PreKeyBundle::new( bob_store.get_local_registration_id(None).await?, 1, // device id None, // no pre key signed_pre_key_id, // signed pre key id bob_signed_pre_key_pair.public_key, bob_signed_pre_key_signature.to_vec(), *bob_store.get_identity_key_pair(None).await?.identity_key(), )?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); let original_message = "L'homme est condamné à être libre"; let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; assert_eq!( outgoing_message.message_type(), CiphertextMessageType::PreKey ); let incoming_message = CiphertextMessage::PreKeySignalMessage( PreKeySignalMessage::try_from(outgoing_message.serialize())?, ); bob_store .save_signed_pre_key( signed_pre_key_id, &SignedPreKeyRecord::new( signed_pre_key_id, /*timestamp*/ 42, &bob_signed_pre_key_pair, &bob_signed_pre_key_signature, ), None, ) .await?; let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), original_message ); Ok(()) } .now_or_never() .expect("sync") } #[test] fn basic_session_v3() -> Result<(), SignalProtocolError> { let (alice_session, bob_session) = initialize_sessions_v3()?; run_session_interaction(alice_session, bob_session)?; Ok(()) } #[test] fn message_key_limits() -> Result<(), SignalProtocolError> { async { let (alice_session_record, bob_session_record) = initialize_sessions_v3()?; let alice_address = ProtocolAddress::new("+14159999999".to_owned(), 1); let bob_address = ProtocolAddress::new("+14158888888".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; alice_store .store_session(&bob_address, &alice_session_record, None) .await?; bob_store .store_session(&alice_address, &bob_session_record, None) .await?; const MAX_MESSAGE_KEYS: usize = 2000; // same value as in library const TOO_MANY_MESSAGES: usize = MAX_MESSAGE_KEYS + 300; let mut inflight = Vec::with_capacity(TOO_MANY_MESSAGES); for i in 0..TOO_MANY_MESSAGES { inflight .push(encrypt(&mut alice_store, &bob_address, &format!("It's over {}", i)).await?); } assert_eq!( String::from_utf8(decrypt(&mut bob_store, &alice_address, &inflight[1000]).await?) .expect("valid utf8"), "It's over 1000" ); assert_eq!( String::from_utf8( decrypt( &mut bob_store, &alice_address, &inflight[TOO_MANY_MESSAGES - 1] ) .await? ) .expect("valid utf8"), format!("It's over {}", TOO_MANY_MESSAGES - 1) ); let err = decrypt(&mut bob_store, &alice_address, &inflight[5]) .await .unwrap_err(); assert!(matches!( err, SignalProtocolError::DuplicatedMessage(2300, 5) )); Ok(()) } .now_or_never() .expect("sync") } #[allow(clippy::needless_range_loop)] fn run_session_interaction( alice_session: SessionRecord, bob_session: SessionRecord, ) -> Result<(), SignalProtocolError> { async { use rand::seq::SliceRandom; let alice_address = ProtocolAddress::new("+14159999999".to_owned(), 1); let bob_address = ProtocolAddress::new("+14158888888".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; alice_store .store_session(&bob_address, &alice_session, None) .await?; bob_store .store_session(&alice_address, &bob_session, None) .await?; let alice_plaintext = "This is Alice's message"; let alice_ciphertext = encrypt(&mut alice_store, &bob_address, alice_plaintext).await?; let bob_decrypted = decrypt(&mut bob_store, &alice_address, &alice_ciphertext).await?; assert_eq!( String::from_utf8(bob_decrypted).expect("valid utf8"), alice_plaintext ); let bob_plaintext = "This is Bob's reply"; let bob_ciphertext = encrypt(&mut bob_store, &alice_address, bob_plaintext).await?; let alice_decrypted = decrypt(&mut alice_store, &bob_address, &bob_ciphertext).await?; assert_eq!( String::from_utf8(alice_decrypted).expect("valid utf8"), bob_plaintext ); const ALICE_MESSAGE_COUNT: usize = 50; const BOB_MESSAGE_COUNT: usize = 50; let mut alice_messages = Vec::with_capacity(ALICE_MESSAGE_COUNT); for i in 0..ALICE_MESSAGE_COUNT { let ptext = format!("смерть за смерть {}", i); let ctext = encrypt(&mut alice_store, &bob_address, &ptext).await?; alice_messages.push((ptext, ctext)); } let mut rng = rand::rngs::OsRng; alice_messages.shuffle(&mut rng); for i in 0..ALICE_MESSAGE_COUNT / 2 { let ptext = decrypt(&mut bob_store, &alice_address, &alice_messages[i].1).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), alice_messages[i].0 ); } let mut bob_messages = Vec::with_capacity(BOB_MESSAGE_COUNT); for i in 0..BOB_MESSAGE_COUNT { let ptext = format!("Relax in the safety of your own delusions. {}", i); let ctext = encrypt(&mut bob_store, &alice_address, &ptext).await?; bob_messages.push((ptext, ctext)); } bob_messages.shuffle(&mut rng); for i in 0..BOB_MESSAGE_COUNT / 2 { let ptext = decrypt(&mut alice_store, &bob_address, &bob_messages[i].1).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), bob_messages[i].0 ); } for i in ALICE_MESSAGE_COUNT / 2..ALICE_MESSAGE_COUNT { let ptext = decrypt(&mut bob_store, &alice_address, &alice_messages[i].1).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), alice_messages[i].0 ); } for i in BOB_MESSAGE_COUNT / 2..BOB_MESSAGE_COUNT { let ptext = decrypt(&mut alice_store, &bob_address, &bob_messages[i].1).await?; assert_eq!( String::from_utf8(ptext).expect("valid utf8"), bob_messages[i].0 ); } Ok(()) } .now_or_never() .expect("sync") } async fn run_interaction( alice_store: &mut InMemSignalProtocolStore, alice_address: &ProtocolAddress, bob_store: &mut InMemSignalProtocolStore, bob_address: &ProtocolAddress, ) -> Result<(), SignalProtocolError> { let alice_ptext = "It's rabbit season"; let alice_message = encrypt(alice_store, bob_address, alice_ptext).await?; assert_eq!(alice_message.message_type(), CiphertextMessageType::Whisper); assert_eq!( String::from_utf8(decrypt(bob_store, alice_address, &alice_message).await?) .expect("valid utf8"), alice_ptext ); let bob_ptext = "It's duck season"; let bob_message = encrypt(bob_store, alice_address, bob_ptext).await?; assert_eq!(bob_message.message_type(), CiphertextMessageType::Whisper); assert_eq!( String::from_utf8(decrypt(alice_store, bob_address, &bob_message).await?) .expect("valid utf8"), bob_ptext ); for i in 0..10 { let alice_ptext = format!("A->B message {}", i); let alice_message = encrypt(alice_store, bob_address, &alice_ptext).await?; assert_eq!(alice_message.message_type(), CiphertextMessageType::Whisper); assert_eq!( String::from_utf8(decrypt(bob_store, alice_address, &alice_message).await?) .expect("valid utf8"), alice_ptext ); } for i in 0..10 { let bob_ptext = format!("B->A message {}", i); let bob_message = encrypt(bob_store, alice_address, &bob_ptext).await?; assert_eq!(bob_message.message_type(), CiphertextMessageType::Whisper); assert_eq!( String::from_utf8(decrypt(alice_store, bob_address, &bob_message).await?) .expect("valid utf8"), bob_ptext ); } let mut alice_ooo_messages = vec![]; for i in 0..10 { let alice_ptext = format!("A->B OOO message {}", i); let alice_message = encrypt(alice_store, bob_address, &alice_ptext).await?; alice_ooo_messages.push((alice_ptext, alice_message)); } for i in 0..10 { let alice_ptext = format!("A->B post-OOO message {}", i); let alice_message = encrypt(alice_store, bob_address, &alice_ptext).await?; assert_eq!(alice_message.message_type(), CiphertextMessageType::Whisper); assert_eq!( String::from_utf8(decrypt(bob_store, alice_address, &alice_message).await?) .expect("valid utf8"), alice_ptext ); } for i in 0..10 { let bob_ptext = format!("B->A message post-OOO {}", i); let bob_message = encrypt(bob_store, alice_address, &bob_ptext).await?; assert_eq!(bob_message.message_type(), CiphertextMessageType::Whisper); assert_eq!( String::from_utf8(decrypt(alice_store, bob_address, &bob_message).await?) .expect("valid utf8"), bob_ptext ); } for (ptext, ctext) in alice_ooo_messages { assert_eq!( String::from_utf8(decrypt(bob_store, alice_address, &ctext).await?) .expect("valid utf8"), ptext ); } Ok(()) } #[allow(clippy::eval_order_dependence)] async fn is_session_id_equal( alice_store: &dyn ProtocolStore, alice_address: &ProtocolAddress, bob_store: &dyn ProtocolStore, bob_address: &ProtocolAddress, ) -> Result { Ok(alice_store .load_session(bob_address, None) .await? .expect("session found") .alice_base_key()? == bob_store .load_session(alice_address, None) .await? .expect("session found") .alice_base_key()?) } #[test] fn basic_simultaneous_initiate() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; process_prekey_bundle( &alice_address, &mut bob_store.session_store, &mut bob_store.identity_store, &alice_pre_key_bundle, &mut csprng, None, ) .await?; let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::PreKey ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::PreKey ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let alice_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_alice.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(alice_plaintext).expect("valid utf8"), "hi alice" ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; assert_eq!( alice_response.message_type(), CiphertextMessageType::Whisper ); let response_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(alice_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "nice to see you" ); assert!(is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await?); let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); let response_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "you as well" ); assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); Ok(()) } .now_or_never() .expect("sync") } #[test] fn simultaneous_initiate_with_lossage() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; process_prekey_bundle( &alice_address, &mut bob_store.session_store, &mut bob_store.identity_store, &alice_pre_key_bundle, &mut csprng, None, ) .await?; let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::PreKey ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::PreKey ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; assert_eq!(alice_response.message_type(), CiphertextMessageType::PreKey); let response_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( alice_response.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "nice to see you" ); assert!(is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await?); let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); let response_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "you as well" ); assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); Ok(()) } .now_or_never() .expect("sync") } #[test] fn simultaneous_initiate_lost_message() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; process_prekey_bundle( &alice_address, &mut bob_store.session_store, &mut bob_store.identity_store, &alice_pre_key_bundle, &mut csprng, None, ) .await?; let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::PreKey ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::PreKey ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let alice_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_alice.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(alice_plaintext).expect("valid utf8"), "hi alice" ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; assert_eq!( alice_response.message_type(), CiphertextMessageType::Whisper ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); let response_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "you as well" ); assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); Ok(()) } .now_or_never() .expect("sync") } #[test] fn simultaneous_initiate_repeated_messages() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; for _ in 0..15 { let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; process_prekey_bundle( &alice_address, &mut bob_store.session_store, &mut bob_store.identity_store, &alice_pre_key_bundle, &mut csprng, None, ) .await?; let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::PreKey ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::PreKey ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); let alice_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_alice.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(alice_plaintext).expect("valid utf8"), "hi alice" ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); } for _ in 0..50 { let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::Whisper ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::Whisper ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); let alice_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from( message_for_alice.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(alice_plaintext).expect("valid utf8"), "hi alice" ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); } let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; assert_eq!( alice_response.message_type(), CiphertextMessageType::Whisper ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); let response_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "you as well" ); assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); Ok(()) } .now_or_never() .expect("sync") } #[test] fn simultaneous_initiate_lost_message_repeated_messages() -> Result<(), SignalProtocolError> { async { let mut csprng = OsRng; let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store()?; let mut bob_store = support::test_in_memory_protocol_store()?; let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; let lost_message_for_bob = encrypt(&mut alice_store, &bob_address, "it was so long ago").await?; for _ in 0..15 { let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut csprng, None, ) .await?; process_prekey_bundle( &alice_address, &mut bob_store.session_store, &mut bob_store.identity_store, &alice_pre_key_bundle, &mut csprng, None, ) .await?; let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::PreKey ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::PreKey ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); let alice_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_alice.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(alice_plaintext).expect("valid utf8"), "hi alice" ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); } for _ in 0..50 { let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; assert_eq!( message_for_bob.message_type(), CiphertextMessageType::Whisper ); assert_eq!( message_for_alice.message_type(), CiphertextMessageType::Whisper ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); let alice_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from( message_for_alice.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(alice_plaintext).expect("valid utf8"), "hi alice" ); let bob_plaintext = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from( message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(bob_plaintext).expect("valid utf8"), "hi bob" ); assert_eq!( alice_store .load_session(&bob_address, None) .await? .expect("session found") .session_version()?, 3 ); assert_eq!( bob_store .load_session(&alice_address, None) .await? .expect("session found") .session_version()?, 3 ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) .await? ); } let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; assert_eq!( alice_response.message_type(), CiphertextMessageType::Whisper ); assert!( !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? ); let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); let response_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "you as well" ); assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); let blast_from_the_past = decrypt( &mut bob_store, &alice_address, &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( lost_message_for_bob.serialize(), )?), ) .await?; assert_eq!( String::from_utf8(blast_from_the_past).expect("valid utf8"), "it was so long ago" ); assert!( !is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await? ); let bob_response = encrypt(&mut bob_store, &alice_address, "so it was").await?; assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); let response_plaintext = decrypt( &mut alice_store, &bob_address, &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), ) .await?; assert_eq!( String::from_utf8(response_plaintext).expect("valid utf8"), "so it was" ); assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); Ok(()) } .now_or_never() .expect("sync") }