// // Copyright 2021 Signal Messenger, LLC. // SPDX-License-Identifier: AGPL-3.0-only // use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use futures_util::FutureExt; use libsignal_protocol::*; use rand::rngs::OsRng; use rand::Rng; use uuid::Uuid; #[path = "../tests/support/mod.rs"] mod support; pub fn v1(c: &mut Criterion) { let mut rng = OsRng; let alice_address = ProtocolAddress::new("9d0652a3-dcc3-4d11-975f-74d61598733f".to_owned(), 1); let bob_address = ProtocolAddress::new("796abedb-ca4e-4f18-8803-1fde5b921f9f".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store().expect("brand new store"); let mut bob_store = support::test_in_memory_protocol_store().expect("brand new store"); let bob_pre_key_bundle = support::create_pre_key_bundle(&mut bob_store, &mut rng) .now_or_never() .expect("sync") .expect("valid"); process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut rng, None, ) .now_or_never() .expect("sync") .expect("valid"); let trust_root = KeyPair::generate(&mut rng); let server_key = KeyPair::generate(&mut rng); let server_cert = ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng) .expect("valid"); let expires = 1605722925; let sender_cert = SenderCertificate::new( alice_address.name().to_string(), None, *alice_store .get_identity_key_pair(None) .now_or_never() .expect("sync") .expect("valid") .public_key(), alice_address.device_id(), expires, server_cert, &server_key.private_key, &mut rng, ) .expect("valid"); let message = b"hello"; let usmc = UnidentifiedSenderMessageContent::new( CiphertextMessageType::Plaintext, sender_cert, message.to_vec(), ContentHint::Default, None, ) .expect("valid"); let mut encrypt_it = || { sealed_sender_encrypt_from_usmc( &bob_address, &usmc, &mut alice_store.identity_store, None, &mut rng, ) .now_or_never() .expect("sync") .expect("valid") }; let encrypted = encrypt_it(); let mut decrypt_it = || { sealed_sender_decrypt_to_usmc(&encrypted, &mut bob_store.identity_store, None) .now_or_never() .expect("sync") .expect("valid") }; assert_eq!(message, decrypt_it().contents().expect("valid")); c.bench_function("v1/encrypt", |b| b.iter(&mut encrypt_it)); c.bench_function("v1/decrypt", |b| b.iter(&mut decrypt_it)); } pub fn v2(c: &mut Criterion) { let mut rng = OsRng; let alice_address = ProtocolAddress::new("9d0652a3-dcc3-4d11-975f-74d61598733f".to_owned(), 1); let bob_address = ProtocolAddress::new("796abedb-ca4e-4f18-8803-1fde5b921f9f".to_owned(), 1); let mut alice_store = support::test_in_memory_protocol_store().expect("brand new store"); let mut bob_store = support::test_in_memory_protocol_store().expect("brand new store"); let bob_pre_key_bundle = support::create_pre_key_bundle(&mut bob_store, &mut rng) .now_or_never() .expect("sync") .expect("valid"); process_prekey_bundle( &bob_address, &mut alice_store.session_store, &mut alice_store.identity_store, &bob_pre_key_bundle, &mut rng, None, ) .now_or_never() .expect("sync") .expect("valid"); let trust_root = KeyPair::generate(&mut rng); let server_key = KeyPair::generate(&mut rng); let server_cert = ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng) .expect("valid"); let expires = 1605722925; let sender_cert = SenderCertificate::new( alice_address.name().to_string(), None, *alice_store .get_identity_key_pair(None) .now_or_never() .expect("sync") .expect("valid") .public_key(), alice_address.device_id(), expires, server_cert, &server_key.private_key, &mut rng, ) .expect("valid"); let message = b"hello"; let usmc = UnidentifiedSenderMessageContent::new( CiphertextMessageType::Plaintext, sender_cert, message.to_vec(), ContentHint::Default, None, ) .expect("valid"); let mut encrypt_it = || { sealed_sender_multi_recipient_encrypt( &[&bob_address], &alice_store .session_store .load_existing_sessions(&[&bob_address]) .expect("present"), &usmc, &mut alice_store.identity_store, None, &mut rng, ) .now_or_never() .expect("sync") .expect("valid") }; let outgoing = encrypt_it(); let incoming = sealed_sender_multi_recipient_fan_out(&outgoing) .expect("valid") .into_iter() .next() .expect("at least one destination"); let mut decrypt_it = || { sealed_sender_decrypt_to_usmc(&incoming, &mut bob_store.identity_store, None) .now_or_never() .expect("sync") .expect("valid") }; assert_eq!(message, decrypt_it().contents().expect("valid")); c.bench_function("v2/encrypt", |b| b.iter(&mut encrypt_it)); c.bench_function("v2/decrypt", |b| b.iter(&mut decrypt_it)); // Fill out additional recipients. let mut recipients = vec![bob_address.clone()]; while recipients.len() < 10 { let next_address = ProtocolAddress::new(Uuid::from_bytes(rng.gen()).to_string(), 1); let mut next_store = support::test_in_memory_protocol_store().expect("brand new store"); let next_pre_key_bundle = support::create_pre_key_bundle(&mut next_store, &mut rng) .now_or_never() .expect("sync") .expect("valid"); process_prekey_bundle( &next_address, &mut alice_store.session_store, &mut alice_store.identity_store, &next_pre_key_bundle, &mut rng, None, ) .now_or_never() .expect("sync") .expect("valid"); recipients.push(next_address); } let mut group = c.benchmark_group("v2/encrypt/multi-recipient"); for recipient_count in [2, 5, 10] { group.bench_with_input( BenchmarkId::from_parameter(recipient_count), &recipient_count, |b, &recipient_count| { let recipients: Vec<_> = recipients.iter().take(recipient_count).collect(); b.iter(|| { sealed_sender_multi_recipient_encrypt( &recipients, &alice_store .session_store .load_existing_sessions(&recipients) .expect("present"), &usmc, &mut alice_store.identity_store, None, &mut rng, ) .now_or_never() .expect("sync") .expect("valid") }); }, ); } group.finish(); let mut group = c.benchmark_group("v2/encrypt/multi-device"); for device_count in [2, 5, 10] { group.bench_with_input( BenchmarkId::from_parameter(device_count), &device_count, |b, &device_count| { let recipients: Vec<_> = vec![&bob_address; device_count]; b.iter(|| { sealed_sender_multi_recipient_encrypt( &recipients, &alice_store .session_store .load_existing_sessions(&recipients) .expect("present"), &usmc, &mut alice_store.identity_store, None, &mut rng, ) .now_or_never() .expect("sync") .expect("valid") }); }, ); } group.finish(); } criterion_group!(benches, v1, v2); criterion_main!(benches);