mirror of
https://github.com/signalapp/libsignal.git
synced 2026-05-03 21:12:20 +02:00
Replace pqclean crate usages with libcrux
This commit is contained in:
@@ -38,21 +38,30 @@ impl super::LibSignalProtocolStore for LibSignalProtocolCurrent {
|
||||
let mut csprng = rng();
|
||||
let pre_key_pair = KeyPair::generate(&mut csprng);
|
||||
let signed_pre_key_pair = KeyPair::generate(&mut csprng);
|
||||
let signed_pq_pre_key_pair = kem::KeyPair::generate(kem::KeyType::Kyber1024);
|
||||
|
||||
let signed_pre_key_public = signed_pre_key_pair.public_key.serialize();
|
||||
let signed_pre_key_signature = self
|
||||
let identity_key = self
|
||||
.0
|
||||
.get_identity_key_pair()
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can fetch identity key")
|
||||
.expect("can fetch identity key");
|
||||
let signed_pre_key_public = signed_pre_key_pair.public_key.serialize();
|
||||
let signed_pre_key_signature = identity_key
|
||||
.private_key()
|
||||
.calculate_signature(&signed_pre_key_public, &mut csprng)
|
||||
.expect("can calculate signatures");
|
||||
|
||||
let signed_pq_pre_key_public = signed_pq_pre_key_pair.public_key.serialize();
|
||||
let signed_pq_pre_key_signature = identity_key
|
||||
.private_key()
|
||||
.calculate_signature(&signed_pq_pre_key_public, &mut csprng)
|
||||
.expect("can sign");
|
||||
|
||||
let device_id: u32 = csprng.random();
|
||||
let pre_key_id: u32 = csprng.random();
|
||||
let signed_pre_key_id: u32 = csprng.random();
|
||||
let kyber_pre_key_id: u32 = csprng.random();
|
||||
|
||||
let pre_key_bundle = PreKeyBundle::new(
|
||||
self.0
|
||||
@@ -73,7 +82,12 @@ impl super::LibSignalProtocolStore for LibSignalProtocolCurrent {
|
||||
.expect("can fetch identity key")
|
||||
.identity_key(),
|
||||
)
|
||||
.expect("can create pre-key bundles");
|
||||
.expect("can create pre-key bundles")
|
||||
.with_kyber_pre_key(
|
||||
kyber_pre_key_id.into(),
|
||||
signed_pq_pre_key_pair.public_key.clone(),
|
||||
signed_pq_pre_key_signature.to_vec(),
|
||||
);
|
||||
|
||||
self.0
|
||||
.save_pre_key(
|
||||
@@ -100,6 +114,20 @@ impl super::LibSignalProtocolStore for LibSignalProtocolCurrent {
|
||||
.expect("synchronous")
|
||||
.expect("can save pre-keys");
|
||||
|
||||
self.0
|
||||
.save_kyber_pre_key(
|
||||
kyber_pre_key_id.into(),
|
||||
&KyberPreKeyRecord::new(
|
||||
kyber_pre_key_id.into(),
|
||||
timestamp,
|
||||
&signed_pq_pre_key_pair,
|
||||
&signed_pq_pre_key_signature,
|
||||
),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can save");
|
||||
|
||||
pre_key_bundle
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ pub trait LibSignalProtocolStore {
|
||||
mod current;
|
||||
pub use current::LibSignalProtocolCurrent;
|
||||
|
||||
mod v70;
|
||||
pub use v70::LibSignalProtocolV70;
|
||||
|
||||
mod v21;
|
||||
pub use v21::LibSignalProtocolV21;
|
||||
|
||||
|
||||
316
rust/protocol/cross-version-testing/src/v70.rs
Normal file
316
rust/protocol/cross-version-testing/src/v70.rs
Normal file
@@ -0,0 +1,316 @@
|
||||
//
|
||||
// Copyright 2023 Signal Messenger, LLC.
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
use futures_util::FutureExt;
|
||||
use libsignal_protocol_v70::*;
|
||||
use rand_v8::{thread_rng, Rng};
|
||||
|
||||
fn address(id: &str) -> ProtocolAddress {
|
||||
ProtocolAddress::new(id.into(), 1.into())
|
||||
}
|
||||
|
||||
pub struct LibSignalProtocolV70(InMemSignalProtocolStore);
|
||||
|
||||
impl LibSignalProtocolV70 {
|
||||
pub fn new() -> Self {
|
||||
let mut csprng = thread_rng();
|
||||
let identity_key = IdentityKeyPair::generate(&mut csprng);
|
||||
// Valid registration IDs fit in 14 bits.
|
||||
let registration_id: u8 = csprng.gen();
|
||||
|
||||
Self(
|
||||
InMemSignalProtocolStore::new(identity_key, registration_id as u32)
|
||||
.expect("can initialize"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl super::LibSignalProtocolStore for LibSignalProtocolV70 {
|
||||
fn version(&self) -> &'static str {
|
||||
"v70"
|
||||
}
|
||||
|
||||
fn create_pre_key_bundle(&mut self) -> super::PreKeyBundle {
|
||||
let mut csprng = thread_rng();
|
||||
let pre_key_pair = KeyPair::generate(&mut csprng);
|
||||
let signed_pre_key_pair = KeyPair::generate(&mut csprng);
|
||||
let signed_pq_pre_key_pair = kem::KeyPair::generate(kem::KeyType::Kyber1024);
|
||||
|
||||
let identity_key = self
|
||||
.0
|
||||
.get_identity_key_pair()
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can fetch identity key");
|
||||
let signed_pre_key_public = signed_pre_key_pair.public_key.serialize();
|
||||
let signed_pre_key_signature = identity_key
|
||||
.private_key()
|
||||
.calculate_signature(&signed_pre_key_public, &mut csprng)
|
||||
.expect("can calculate signatures");
|
||||
|
||||
let signed_pq_pre_key_public = signed_pq_pre_key_pair.public_key.serialize();
|
||||
let signed_pq_pre_key_signature = identity_key
|
||||
.private_key()
|
||||
.calculate_signature(&signed_pq_pre_key_public, &mut csprng)
|
||||
.expect("can sign");
|
||||
|
||||
let device_id: u32 = csprng.gen();
|
||||
let pre_key_id: u32 = csprng.gen();
|
||||
let signed_pre_key_id: u32 = csprng.gen();
|
||||
let kyber_pre_key_id: u32 = csprng.gen();
|
||||
|
||||
let pre_key_bundle = super::PreKeyBundle::new(
|
||||
self.0
|
||||
.get_local_registration_id()
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can fetch registration id"),
|
||||
device_id.into(),
|
||||
Some((pre_key_id.into(), pre_key_pair.public_key.into_current())),
|
||||
signed_pre_key_id.into(),
|
||||
signed_pre_key_pair.public_key.into_current(),
|
||||
signed_pre_key_signature.to_vec(),
|
||||
self.0
|
||||
.get_identity_key_pair()
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can fetch identity key")
|
||||
.identity_key()
|
||||
.clone()
|
||||
.into_current(),
|
||||
)
|
||||
.expect("can create pre-key bundles")
|
||||
.with_kyber_pre_key(
|
||||
kyber_pre_key_id.into(),
|
||||
signed_pq_pre_key_pair.public_key.clone().into_current(),
|
||||
signed_pq_pre_key_signature.to_vec(),
|
||||
);
|
||||
|
||||
self.0
|
||||
.save_pre_key(
|
||||
pre_key_id.into(),
|
||||
&PreKeyRecord::new(pre_key_id.into(), &pre_key_pair),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can save pre-keys");
|
||||
|
||||
let timestamp = csprng.gen();
|
||||
|
||||
self.0
|
||||
.save_signed_pre_key(
|
||||
signed_pre_key_id.into(),
|
||||
&SignedPreKeyRecord::new(
|
||||
signed_pre_key_id.into(),
|
||||
timestamp,
|
||||
&signed_pre_key_pair,
|
||||
&signed_pre_key_signature,
|
||||
),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can save pre-keys");
|
||||
|
||||
self.0
|
||||
.save_kyber_pre_key(
|
||||
kyber_pre_key_id.into(),
|
||||
&KyberPreKeyRecord::new(
|
||||
kyber_pre_key_id.into(),
|
||||
timestamp,
|
||||
&signed_pq_pre_key_pair,
|
||||
&signed_pq_pre_key_signature,
|
||||
),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can save");
|
||||
|
||||
pre_key_bundle
|
||||
}
|
||||
|
||||
fn process_pre_key_bundle(&mut self, remote: &str, pre_key_bundle: super::PreKeyBundle) {
|
||||
let pre_key_bundle = (|| {
|
||||
let mut bundle = PreKeyBundle::new(
|
||||
pre_key_bundle.registration_id()?,
|
||||
ConvertVersion::from_current(pre_key_bundle.device_id()?),
|
||||
pre_key_bundle
|
||||
.pre_key_id()?
|
||||
.map(ConvertVersion::from_current)
|
||||
.zip(
|
||||
pre_key_bundle
|
||||
.pre_key_public()?
|
||||
.map(ConvertVersion::from_current),
|
||||
),
|
||||
u32::from(pre_key_bundle.signed_pre_key_id()?).into(),
|
||||
ConvertVersion::from_current(pre_key_bundle.signed_pre_key_public()?),
|
||||
pre_key_bundle.signed_pre_key_signature()?.to_vec(),
|
||||
ConvertVersion::from_current(pre_key_bundle.identity_key()?.to_owned()),
|
||||
)
|
||||
.expect("can produce bundle");
|
||||
let kyber_keys = pre_key_bundle
|
||||
.kyber_pre_key_id()?
|
||||
.zip(pre_key_bundle.kyber_pre_key_public()?)
|
||||
.zip(pre_key_bundle.kyber_pre_key_signature()?);
|
||||
|
||||
if let Some(((id, key), signature)) = kyber_keys {
|
||||
bundle = bundle.with_kyber_pre_key(
|
||||
ConvertVersion::from_current(id),
|
||||
ConvertVersion::from_current(key.clone()),
|
||||
signature.to_vec(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok::<_, libsignal_protocol_current::SignalProtocolError>(bundle)
|
||||
})()
|
||||
.expect("can retrieve values");
|
||||
process_prekey_bundle(
|
||||
&address(remote),
|
||||
&mut self.0.session_store,
|
||||
&mut self.0.identity_store,
|
||||
&pre_key_bundle,
|
||||
SystemTime::now(),
|
||||
&mut thread_rng(),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can process pre-key bundles")
|
||||
}
|
||||
|
||||
fn encrypt(&mut self, remote: &str, msg: &[u8]) -> (Vec<u8>, super::CiphertextMessageType) {
|
||||
let encrypted = message_encrypt(
|
||||
msg,
|
||||
&address(remote),
|
||||
&mut self.0.session_store,
|
||||
&mut self.0.identity_store,
|
||||
SystemTime::now(),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can encrypt messages");
|
||||
(
|
||||
encrypted.serialize().to_vec(),
|
||||
encrypted.message_type().into_current(),
|
||||
)
|
||||
}
|
||||
|
||||
fn decrypt(
|
||||
&mut self,
|
||||
remote: &str,
|
||||
msg: &[u8],
|
||||
msg_type: super::CiphertextMessageType,
|
||||
) -> Vec<u8> {
|
||||
match ConvertVersion::from_current(msg_type) {
|
||||
CiphertextMessageType::Whisper => message_decrypt_signal(
|
||||
&SignalMessage::try_from(msg).expect("valid"),
|
||||
&address(remote),
|
||||
&mut self.0.session_store,
|
||||
&mut self.0.identity_store,
|
||||
&mut thread_rng(),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can decrypt messages"),
|
||||
CiphertextMessageType::PreKey => message_decrypt_prekey(
|
||||
&PreKeySignalMessage::try_from(msg).expect("valid"),
|
||||
&address(remote),
|
||||
&mut self.0.session_store,
|
||||
&mut self.0.identity_store,
|
||||
&mut self.0.pre_key_store,
|
||||
&mut self.0.signed_pre_key_store,
|
||||
&mut self.0.kyber_pre_key_store,
|
||||
&mut thread_rng(),
|
||||
)
|
||||
.now_or_never()
|
||||
.expect("synchronous")
|
||||
.expect("can decrypt messages"),
|
||||
_ => panic!("unexpected 1:1 message type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ConvertVersion {
|
||||
type Current;
|
||||
fn into_current(self) -> Self::Current;
|
||||
fn from_current(current: Self::Current) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! impl_convert_version {
|
||||
($old:ty, $current:ty as serializable) => {
|
||||
impl ConvertVersion for $old {
|
||||
type Current = $current;
|
||||
fn from_current(current: Self::Current) -> Self {
|
||||
current
|
||||
.serialize()
|
||||
.as_ref()
|
||||
.try_into()
|
||||
.expect("compatible serialization")
|
||||
}
|
||||
fn into_current(self) -> Self::Current {
|
||||
self.serialize()
|
||||
.as_ref()
|
||||
.try_into()
|
||||
.expect("compatible serialization")
|
||||
}
|
||||
}
|
||||
};
|
||||
($old:ty, $current:ty as u32) => {
|
||||
impl ConvertVersion for $old {
|
||||
type Current = $current;
|
||||
fn from_current(current: Self::Current) -> Self {
|
||||
u32::from(current).into()
|
||||
}
|
||||
fn into_current(self) -> Self::Current {
|
||||
u32::from(self).into()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_convert_version!(
|
||||
PublicKey,
|
||||
libsignal_protocol_current::PublicKey as serializable
|
||||
);
|
||||
impl_convert_version!(
|
||||
IdentityKey,
|
||||
libsignal_protocol_current::IdentityKey as serializable
|
||||
);
|
||||
impl_convert_version!(
|
||||
kem::PublicKey,
|
||||
libsignal_protocol_current::kem::PublicKey as serializable
|
||||
);
|
||||
impl_convert_version!(
|
||||
kem::SecretKey,
|
||||
libsignal_protocol_current::kem::SecretKey as serializable
|
||||
);
|
||||
impl_convert_version!(DeviceId, libsignal_protocol_current::DeviceId as u32);
|
||||
impl_convert_version!(PreKeyId, libsignal_protocol_current::PreKeyId as u32);
|
||||
impl_convert_version!(
|
||||
KyberPreKeyId,
|
||||
libsignal_protocol_current::KyberPreKeyId as u32
|
||||
);
|
||||
|
||||
impl ConvertVersion for CiphertextMessageType {
|
||||
type Current = libsignal_protocol_current::CiphertextMessageType;
|
||||
|
||||
fn into_current(self) -> Self::Current {
|
||||
match self {
|
||||
CiphertextMessageType::Whisper => Self::Current::Whisper,
|
||||
CiphertextMessageType::PreKey => Self::Current::PreKey,
|
||||
CiphertextMessageType::SenderKey => Self::Current::SenderKey,
|
||||
CiphertextMessageType::Plaintext => Self::Current::Plaintext,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_current(current: Self::Current) -> Self {
|
||||
match current {
|
||||
Self::Current::Whisper => Self::Whisper,
|
||||
Self::Current::PreKey => Self::PreKey,
|
||||
Self::Current::SenderKey => Self::SenderKey,
|
||||
Self::Current::Plaintext => Self::Plaintext,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user