cross-version: Add a test for sealed sender messages

This commit is contained in:
Jordan Rose
2025-06-13 17:03:52 -07:00
parent 1ed212371e
commit 0760d3bc5d
5 changed files with 265 additions and 1 deletions

View File

@@ -0,0 +1,146 @@
//
// Copyright 2025 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
use libsignal_protocol_cross_version_testing::*;
use libsignal_protocol_current::{
ContentHint, DeviceId, KeyPair, SealedSenderV2SentMessage, SenderCertificate,
ServerCertificate, Timestamp,
};
use rand::rng;
const BOB_UUID: uuid::Uuid = uuid::uuid!("b000000b-6199-486a-ba89-2ba2bb4f2154");
fn make_alice_sender_cert(alice_store: &mut dyn LibSignalProtocolStore) -> SenderCertificate {
let fake_trust_root = KeyPair::generate(&mut rng());
let signer_key = KeyPair::generate(&mut rng());
let server_cert = ServerCertificate::new(
0xfa75e,
signer_key.public_key,
&fake_trust_root.private_key,
&mut rng(),
)
.expect("valid");
let identity_key = *alice_store
.create_pre_key_bundle()
.identity_key()
.expect("has identity key");
SenderCertificate::new(
"alice".to_owned(),
Some("+16505550101".to_owned()),
*identity_key.public_key(),
DeviceId::new(1).expect("valid"),
Timestamp::from_epoch_millis(0),
server_cert,
&signer_key.private_key,
&mut rng(),
)
.expect("valid")
}
fn assert_eq_usmc(
original: &UnidentifiedSenderMessageContent,
decrypted: &UnidentifiedSenderMessageContent,
) {
// Check the fields rather than just re-serializing to make sure the protobuf definition hasn't
// changed either. But we also re-serialize in case a field is added that's not checked here.
assert_eq!(
original.msg_type().expect("has field"),
decrypted.msg_type().expect("has field")
);
assert_eq!(
original.contents().expect("has field"),
decrypted.contents().expect("has field")
);
assert_eq!(
original.group_id().expect("has field"),
decrypted.group_id().expect("has field")
);
assert_eq!(
original.content_hint().expect("has field"),
decrypted.content_hint().expect("has field")
);
assert_eq!(
original
.sender()
.expect("has field")
.serialized()
.expect("can serialize"),
decrypted
.sender()
.expect("has field")
.serialized()
.expect("can serialize"),
);
assert_eq!(
original.serialized().expect("can serialize the whole USMC"),
decrypted
.serialized()
.expect("can serialize the whole USMC"),
);
}
#[test]
fn ssv1() {
try_all_combinations(run, &[|| Box::new(LibSignalProtocolV70::new())]);
fn run(
alice_store: &mut dyn LibSignalProtocolStore,
bob_store: &mut dyn LibSignalProtocolStore,
) {
alice_store
.process_pre_key_bundle(&BOB_UUID.to_string(), bob_store.create_pre_key_bundle());
let message = UnidentifiedSenderMessageContent::new(
CiphertextMessageType::SenderKey,
make_alice_sender_cert(alice_store),
b"payload".to_vec(),
ContentHint::Resendable,
Some(b"group".to_vec()),
)
.expect("valid");
let encrypted = alice_store.encrypt_sealed_sender_v1(&BOB_UUID.to_string(), &message);
let decrypted = bob_store.decrypt_sealed_sender(&encrypted);
assert_eq_usmc(&message, &decrypted);
}
}
#[test]
fn ssv2() {
try_all_combinations(run, &[|| Box::new(LibSignalProtocolV70::new())]);
fn run(
alice_store: &mut dyn LibSignalProtocolStore,
bob_store: &mut dyn LibSignalProtocolStore,
) {
alice_store
.process_pre_key_bundle(&BOB_UUID.to_string(), bob_store.create_pre_key_bundle());
let message = UnidentifiedSenderMessageContent::new(
CiphertextMessageType::SenderKey,
make_alice_sender_cert(alice_store),
b"payload".to_vec(),
ContentHint::Resendable,
Some(b"group".to_vec()),
)
.expect("valid");
let encrypted_to_send =
alice_store.encrypt_sealed_sender_v2(&BOB_UUID.to_string(), &message);
let parsed_encrypted_to_send =
SealedSenderV2SentMessage::parse(&encrypted_to_send).expect("valid");
assert_eq!(1, parsed_encrypted_to_send.recipients.len());
let encrypted_to_receive = parsed_encrypted_to_send
.received_message_parts_for_recipient(&parsed_encrypted_to_send.recipients[0])
.as_ref()
.concat();
let decrypted = bob_store.decrypt_sealed_sender(&encrypted_to_receive);
assert_eq_usmc(&message, &decrypted);
}
}