From 26c036e5915983692ac2349251c88077173d3fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20F=C3=A9ron?= Date: Sat, 13 Apr 2024 10:21:40 +0200 Subject: [PATCH] Various cleanups after merging ACI/PNI (#298) * Use enum variants in a bunch of errors instead of static strings * Rename VerifyAccountResponse::uuid to VerifyAccountResponse::aci for completion (but use a serde alias) * Use IdentityKey in some places where PublicKey was used before (and change the relevant serde modules) --- libsignal-service/examples/storage.rs | 17 +- libsignal-service/src/account_manager.rs | 44 ++--- libsignal-service/src/cipher.rs | 3 +- libsignal-service/src/groups_v2/manager.rs | 1 + libsignal-service/src/lib.rs | 5 +- libsignal-service/src/pre_keys.rs | 28 +++- libsignal-service/src/provisioning/cipher.rs | 12 +- libsignal-service/src/provisioning/mod.rs | 165 +++++++++++-------- libsignal-service/src/push_service.rs | 7 +- libsignal-service/src/sender.rs | 8 +- libsignal-service/src/session_store.rs | 64 +++---- libsignal-service/src/utils.rs | 24 +-- 12 files changed, 202 insertions(+), 176 deletions(-) diff --git a/libsignal-service/examples/storage.rs b/libsignal-service/examples/storage.rs index 11945874d..d9ec45edf 100644 --- a/libsignal-service/examples/storage.rs +++ b/libsignal-service/examples/storage.rs @@ -1,4 +1,4 @@ -use libsignal_service::pre_keys::{PreKeysStore, ServiceKyberPreKeyStore}; +use libsignal_service::pre_keys::{KyberPreKeyStoreExt, PreKeysStore}; use libsignal_service::protocol::{ Direction, IdentityKey, IdentityKeyPair, IdentityKeyStore, KyberPreKeyId, KyberPreKeyRecord, KyberPreKeyStore, PreKeyId, PreKeyRecord, PreKeyStore, @@ -92,7 +92,7 @@ impl SignedPreKeyStore for ExampleStore { } #[async_trait::async_trait(?Send)] -impl ServiceKyberPreKeyStore for ExampleStore { +impl KyberPreKeyStoreExt for ExampleStore { async fn store_last_resort_kyber_pre_key( &mut self, _kyber_prekey_id: KyberPreKeyId, @@ -227,6 +227,19 @@ impl PreKeysStore for ExampleStore { ) -> Result<(), SignalProtocolError> { todo!() } + + async fn signed_pre_keys_count( + &self, + ) -> Result { + todo!() + } + + async fn kyber_pre_keys_count( + &self, + _last_resort: bool, + ) -> Result { + todo!() + } } #[allow(dead_code)] diff --git a/libsignal-service/src/account_manager.rs b/libsignal-service/src/account_manager.rs index f379975f5..e151b476b 100644 --- a/libsignal-service/src/account_manager.rs +++ b/libsignal-service/src/account_manager.rs @@ -10,7 +10,7 @@ use hmac::{Hmac, Mac}; use libsignal_protocol::{ kem, GenericSignedPreKey, IdentityKey, IdentityKeyStore, KeyPair, KyberPreKeyRecord, PrivateKey, ProtocolStore, PublicKey, SenderKeyStore, - SignalProtocolError, SignedPreKeyRecord, + SignedPreKeyRecord, }; use prost::Message; use serde::{Deserialize, Serialize}; @@ -64,20 +64,6 @@ pub enum ProfileManagerError { ProfileCipherError(#[from] ProfileCipherError), } -#[derive(thiserror::Error, Debug)] -pub enum LinkError { - #[error(transparent)] - ServiceError(#[from] ServiceError), - #[error("TsUrl has an invalid UUID field")] - InvalidUuid, - #[error("TsUrl has an invalid pub_key field")] - InvalidPublicKey, - #[error("Protocol error {0}")] - ProtocolError(#[from] SignalProtocolError), - #[error(transparent)] - ProvisioningError(#[from] ProvisioningError), -} - #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct Profile { pub name: Option>, @@ -111,7 +97,6 @@ impl AccountManager { service_id_type: ServiceIdType, csprng: &mut R, use_last_resort_key: bool, - force: bool, ) -> Result<(), ServiceError> { let prekey_status = match self .service @@ -143,7 +128,9 @@ impl AccountManager { if prekey_status.count >= PRE_KEY_MINIMUM && prekey_status.pq_count >= PRE_KEY_MINIMUM { - if !force { + if protocol_store.signed_pre_keys_count().await? > 0 + && protocol_store.kyber_pre_keys_count(true).await? > 0 + { tracing::debug!("Available keys sufficient"); return Ok(()); } @@ -159,6 +146,7 @@ impl AccountManager { .load_last_resort_kyber_pre_keys() .instrument(tracing::trace_span!("fetch last resort key")) .await?; + // XXX: Maybe this check should be done in the generate_pre_keys function? let has_last_resort_key = !last_resort_keys.is_empty(); @@ -186,7 +174,7 @@ impl AccountManager { .transpose()? }; - let identity_key = *identity_key_pair.identity_key().public_key(); + let identity_key = *identity_key_pair.identity_key(); let pre_keys: Vec<_> = pre_keys .into_iter() @@ -289,16 +277,18 @@ impl AccountManager { aci_identity_store: &dyn IdentityKeyStore, pni_identity_store: &dyn IdentityKeyStore, credentials: ServiceCredentials, - ) -> Result<(), LinkError> { + ) -> Result<(), ProvisioningError> { let query: HashMap<_, _> = url.query_pairs().collect(); - let ephemeral_id = query.get("uuid").ok_or(LinkError::InvalidUuid)?; - let pub_key = - query.get("pub_key").ok_or(LinkError::InvalidPublicKey)?; + let ephemeral_id = + query.get("uuid").ok_or(ProvisioningError::MissingUuid)?; + let pub_key = query + .get("pub_key") + .ok_or(ProvisioningError::MissingPublicKey)?; let pub_key = BASE64_RELAXED .decode(&**pub_key) - .map_err(|_e| LinkError::InvalidPublicKey)?; + .map_err(|e| ProvisioningError::InvalidPublicKey(e.into()))?; let pub_key = PublicKey::deserialize(&pub_key) - .map_err(|_e| LinkError::InvalidPublicKey)?; + .map_err(|e| ProvisioningError::InvalidPublicKey(e.into()))?; let aci_identity_key_pair = aci_identity_store.get_identity_key_pair().await?; @@ -361,7 +351,7 @@ impl AccountManager { aci_protocol_store: &mut Aci, pni_protocol_store: &mut Pni, skip_device_transfer: bool, - ) -> Result { + ) -> Result { let aci_identity_key_pair = aci_protocol_store .get_identity_key_pair() .instrument(tracing::trace_span!("get ACI identity key pair")) @@ -421,8 +411,8 @@ impl AccountManager { registration_method, account_attributes, skip_device_transfer, - *aci_identity_key, - *pni_identity_key, + aci_identity_key, + pni_identity_key, dar, ) .await?; diff --git a/libsignal-service/src/cipher.rs b/libsignal-service/src/cipher.rs index 7e65c4f7e..e448576cf 100644 --- a/libsignal-service/src/cipher.rs +++ b/libsignal-service/src/cipher.rs @@ -21,6 +21,7 @@ use crate::{ envelope::Envelope, push_service::ServiceError, sender::OutgoingPushMessage, + session_store::SessionStoreExt, utils::BASE64_RELAXED, ServiceAddress, }; @@ -75,7 +76,7 @@ fn debug_envelope(envelope: &Envelope) -> String { impl ServiceCipher where - S: ProtocolStore + KyberPreKeyStore + SenderKeyStore + Clone, + S: ProtocolStore + SenderKeyStore + SessionStoreExt + Clone, R: Rng + CryptoRng, { pub fn new( diff --git a/libsignal-service/src/groups_v2/manager.rs b/libsignal-service/src/groups_v2/manager.rs index 522a6448a..f413c828b 100644 --- a/libsignal-service/src/groups_v2/manager.rs +++ b/libsignal-service/src/groups_v2/manager.rs @@ -330,6 +330,7 @@ pub fn decrypt_group( fn current_days_seconds() -> (u64, u64) { let days_seconds = |date: NaiveDate| { date.and_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()) + .and_utc() .timestamp() as u64 }; diff --git a/libsignal-service/src/lib.rs b/libsignal-service/src/lib.rs index 9b15aab16..2daaf8ca4 100644 --- a/libsignal-service/src/lib.rs +++ b/libsignal-service/src/lib.rs @@ -32,8 +32,7 @@ pub mod utils; pub mod websocket; pub use crate::account_manager::{ - decrypt_device_name, AccountManager, LinkError, Profile, - ProfileManagerError, + decrypt_device_name, AccountManager, Profile, ProfileManagerError, }; pub use crate::service_address::*; @@ -96,7 +95,7 @@ pub mod prelude { profiles::ProfileKey, }; - pub use libsignal_protocol::DeviceId; + pub use libsignal_protocol::{DeviceId, IdentityKeyStore}; } pub use libsignal_protocol as protocol; diff --git a/libsignal-service/src/pre_keys.rs b/libsignal-service/src/pre_keys.rs index 587ff1ee5..a6687a080 100644 --- a/libsignal-service/src/pre_keys.rs +++ b/libsignal-service/src/pre_keys.rs @@ -1,12 +1,12 @@ use std::{convert::TryFrom, time::SystemTime}; -use crate::utils::{serde_base64, serde_public_key}; +use crate::utils::{serde_base64, serde_identity_key}; use async_trait::async_trait; use libsignal_protocol::{ - error::SignalProtocolError, kem, GenericSignedPreKey, IdentityKeyPair, - IdentityKeyStore, KeyPair, KyberPreKeyId, KyberPreKeyRecord, - KyberPreKeyStore, PreKeyRecord, PreKeyStore, PublicKey, SignedPreKeyRecord, - SignedPreKeyStore, + error::SignalProtocolError, kem, GenericSignedPreKey, IdentityKey, + IdentityKeyPair, IdentityKeyStore, KeyPair, KyberPreKeyId, + KyberPreKeyRecord, KyberPreKeyStore, PreKeyRecord, PreKeyStore, + SignedPreKeyRecord, SignedPreKeyStore, }; use serde::{Deserialize, Serialize}; @@ -16,7 +16,7 @@ use tracing::Instrument; /// Additional methods for the Kyber pre key store /// /// Analogue of Android's ServiceKyberPreKeyStore -pub trait ServiceKyberPreKeyStore: KyberPreKeyStore { +pub trait KyberPreKeyStoreExt: KyberPreKeyStore { async fn store_last_resort_kyber_pre_key( &mut self, kyber_prekey_id: KyberPreKeyId, @@ -55,7 +55,7 @@ pub trait PreKeysStore: + IdentityKeyStore + SignedPreKeyStore + KyberPreKeyStore - + ServiceKyberPreKeyStore + + KyberPreKeyStoreExt { /// ID of the next pre key async fn next_pre_key_id(&self) -> Result; @@ -83,6 +83,16 @@ pub trait PreKeysStore: &mut self, id: u32, ) -> Result<(), SignalProtocolError>; + + /// number of signed pre-keys we currently have in store + async fn signed_pre_keys_count(&self) + -> Result; + + /// number of kyber pre-keys we currently have in store + async fn kyber_pre_keys_count( + &self, + last_resort: bool, + ) -> Result; } #[derive(Debug, Deserialize, Serialize)] @@ -169,8 +179,8 @@ impl TryFrom for KyberPreKeyEntity { pub struct PreKeyState { pub pre_keys: Vec, pub signed_pre_key: SignedPreKeyEntity, - #[serde(with = "serde_public_key")] - pub identity_key: PublicKey, + #[serde(with = "serde_identity_key")] + pub identity_key: IdentityKey, #[serde(skip_serializing_if = "Option::is_none")] pub pq_last_resort_key: Option, pub pq_pre_keys: Vec, diff --git a/libsignal-service/src/provisioning/cipher.rs b/libsignal-service/src/provisioning/cipher.rs index 4dae2a540..7143385bf 100644 --- a/libsignal-service/src/provisioning/cipher.rs +++ b/libsignal-service/src/provisioning/cipher.rs @@ -138,9 +138,7 @@ impl ProvisioningCipher { .body .expect("no body in ProvisionMessage"); if body[0] != VERSION { - return Err(ProvisioningError::InvalidData { - reason: "Bad version number".into(), - }); + return Err(ProvisioningError::BadVersionNumber); } let iv = &body[IV_OFFSET..(IV_LENGTH + IV_OFFSET)]; @@ -166,9 +164,7 @@ impl ProvisioningCipher { let our_mac = verifier.finalize().into_bytes(); debug_assert_eq!(our_mac.len(), mac.len()); if &our_mac[..32] != mac { - return Err(ProvisioningError::InvalidData { - reason: "wrong MAC".into(), - }); + return Err(ProvisioningError::MismatchedMac); } // libsignal-service-java uses Pkcs5, @@ -177,9 +173,7 @@ impl ProvisioningCipher { let cipher = cbc::Decryptor::::new(parts1.into(), iv.into()); let input = cipher .decrypt_padded_vec_mut::(cipher_text) - .map_err(|e| ProvisioningError::InvalidData { - reason: format!("CBC/Padding error: {:?}", e).into(), - })?; + .map_err(ProvisioningError::AesPaddingError)?; Ok(prost::Message::decode(Bytes::from(input))?) } diff --git a/libsignal-service/src/provisioning/mod.rs b/libsignal-service/src/provisioning/mod.rs index e3ae330d9..e1f296d10 100644 --- a/libsignal-service/src/provisioning/mod.rs +++ b/libsignal-service/src/provisioning/mod.rs @@ -1,8 +1,8 @@ mod cipher; mod pipe; +use std::array::TryFromSliceError; use std::convert::TryInto; -use std::{array::TryFromSliceError, borrow::Cow}; pub use cipher::ProvisioningCipher; @@ -11,7 +11,7 @@ use derivative::Derivative; use futures::StreamExt; use futures::{channel::mpsc::Sender, pin_mut, SinkExt}; use libsignal_protocol::{ - DeviceId, IdentityKey, IdentityKeyPair, PrivateKey, PublicKey, SessionStore, + DeviceId, IdentityKey, IdentityKeyPair, PrivateKey, PublicKey, }; use prost::Message; use serde::{Deserialize, Serialize}; @@ -40,8 +40,38 @@ pub use crate::proto::{ #[derive(thiserror::Error, Debug)] pub enum ProvisioningError { - #[error("Invalid provisioning data: {reason}")] - InvalidData { reason: Cow<'static, str> }, + #[error("no provisioning URL received")] + MissingUrl, + #[error("bad version number (unsupported)")] + BadVersionNumber, + #[error("missing public key")] + MissingPublicKey, + #[error("missing private key")] + MissingPrivateKey, + #[error("invalid public key")] + InvalidPublicKey(InvalidKeyError), + #[error("invalid privat key")] + InvalidPrivateKey(InvalidKeyError), + #[error("missing UUID")] + MissingUuid, + #[error("no provisioning message received")] + MissingMessage, + #[error("missing profile key")] + MissingProfileKey, + #[error("missing phone number")] + MissingPhoneNumber, + #[error("invalid phone number: {0}")] + InvalidPhoneNumber(phonenumber::ParseError), + #[error("missing provisioning code")] + MissingProvisioningCode, + #[error("mismatched MAC")] + MismatchedMac, + #[error("AES CBC padding error: {0}")] + AesPaddingError(aes::cipher::block_padding::UnpadError), + + #[error("invalid provisioning step received")] + InvalidStep, + #[error("Protobuf decoding error: {0}")] DecodeError(#[from] prost::DecodeError), #[error("Websocket error: {reason}")] @@ -51,13 +81,21 @@ pub enum ProvisioningError { #[error("Service error: {0}")] ServiceError(#[from] ServiceError), #[error("libsignal-protocol error: {0}")] - ProtocolError(#[from] libsignal_protocol::error::SignalProtocolError), + ProtocolError(#[from] libsignal_protocol::SignalProtocolError), #[error("ProvisioningCipher in encrypt-only mode")] EncryptOnlyProvisioningCipher, #[error("invalid profile key bytes")] InvalidProfileKey(TryFromSliceError), } +#[derive(Debug, thiserror::Error)] +pub enum InvalidKeyError { + #[error("base64 decoding error: {0}")] + Base64(#[from] base64::DecodeError), + #[error("protocol error: {0}")] + Protocol(#[from] libsignal_protocol::SignalProtocolError), +} + pub fn generate_registration_id( csprng: &mut R, ) -> u32 { @@ -111,7 +149,7 @@ pub struct NewDeviceRegistration { pub async fn link_device< R: rand::Rng + rand::CryptoRng, - Aci: PreKeysStore + SessionStore, + Aci: PreKeysStore, Pni: PreKeysStore, P: PushService + Clone, >( @@ -140,79 +178,68 @@ pub async fn link_device< let provision_stream = provisioning_pipe.stream(); pin_mut!(provision_stream); - if let ProvisioningStep::Url(url) = provision_stream.next().await.ok_or( - ProvisioningError::InvalidData { - reason: "no provisioning URL received".into(), - }, - )?? { + if let ProvisioningStep::Url(url) = provision_stream + .next() + .await + .ok_or(ProvisioningError::MissingUrl)?? + { tx.send(SecondaryDeviceProvisioning::Url(url)) .await .expect("failed to send provisioning Url in channel"); } else { - return Err(ProvisioningError::InvalidData { - reason: "wrong provisioning step received".into(), - }); + return Err(ProvisioningError::InvalidStep); } if let ProvisioningStep::Message(message) = - provision_stream.next().await.ok_or( - ProvisioningError::InvalidData { - reason: "no provisioning message received".into(), - }, - )?? + provision_stream + .next() + .await + .ok_or(ProvisioningError::MissingMessage)?? { - let aci_public_key = - PublicKey::deserialize(&message.aci_identity_key_public.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?)?; + let aci_public_key = PublicKey::deserialize( + &message + .aci_identity_key_public + .ok_or(ProvisioningError::MissingPublicKey)?, + ) + .map_err(|e| ProvisioningError::InvalidPublicKey(e.into()))?; let aci_public_key = IdentityKey::new(aci_public_key); - let aci_private_key = - PrivateKey::deserialize(&message.aci_identity_key_private.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?)?; + let aci_private_key = PrivateKey::deserialize( + &message + .aci_identity_key_private + .ok_or(ProvisioningError::MissingPrivateKey)?, + ) + .map_err(|e| ProvisioningError::InvalidPrivateKey(e.into()))?; - let pni_public_key = - PublicKey::deserialize(&message.pni_identity_key_public.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?)?; + let pni_public_key = PublicKey::deserialize( + &message + .pni_identity_key_public + .ok_or(ProvisioningError::MissingPublicKey)?, + ) + .map_err(|e| ProvisioningError::InvalidPublicKey(e.into()))?; let pni_public_key = IdentityKey::new(pni_public_key); - let pni_private_key = - PrivateKey::deserialize(&message.pni_identity_key_private.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?)?; - - let profile_key = - message.profile_key.ok_or(ProvisioningError::InvalidData { - reason: "missing profile key".into(), - })?; - - let phone_number = - message.number.ok_or(ProvisioningError::InvalidData { - reason: "missing phone number".into(), - })?; - - let phone_number = - phonenumber::parse(None, phone_number).map_err(|e| { - ProvisioningError::InvalidData { - reason: format!("invalid phone number ({})", e).into(), - } - })?; - - let provisioning_code = message.provisioning_code.ok_or( - ProvisioningError::InvalidData { - reason: "no provisioning confirmation code".into(), - }, - )?; + let pni_private_key = PrivateKey::deserialize( + &message + .pni_identity_key_private + .ok_or(ProvisioningError::MissingPrivateKey)?, + ) + .map_err(|e| ProvisioningError::InvalidPrivateKey(e.into()))?; + + let profile_key = message + .profile_key + .ok_or(ProvisioningError::MissingProfileKey)?; + + let phone_number = message + .number + .ok_or(ProvisioningError::MissingPhoneNumber)?; + + let phone_number = phonenumber::parse(None, phone_number) + .map_err(ProvisioningError::InvalidPhoneNumber)?; + + let provisioning_code = message + .provisioning_code + .ok_or(ProvisioningError::MissingProvisioningCode)?; let aci_key_pair = IdentityKeyPair::new(aci_public_key, aci_private_key); @@ -233,6 +260,7 @@ pub async fn link_device< 0, ) .await?; + let aci_pq_last_resort_pre_key = aci_pq_last_resort_pre_key.expect("requested last resort key"); assert!(_aci_pre_keys.is_empty()); @@ -252,6 +280,7 @@ pub async fn link_device< 0, ) .await?; + let pni_pq_last_resort_pre_key = pni_pq_last_resort_pre_key.expect("requested last resort key"); assert!(_pni_pre_keys.is_empty()); @@ -319,9 +348,7 @@ pub async fn link_device< .await .expect("failed to send provisioning message in rx channel"); } else { - return Err(ProvisioningError::InvalidData { - reason: "wrong provisioning step received".into(), - }); + return Err(ProvisioningError::InvalidStep); } Ok(()) diff --git a/libsignal-service/src/push_service.rs b/libsignal-service/src/push_service.rs index c6f5beb95..8575f5d32 100644 --- a/libsignal-service/src/push_service.rs +++ b/libsignal-service/src/push_service.rs @@ -297,7 +297,8 @@ pub struct RegistrationLockFailure { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VerifyAccountResponse { - pub uuid: Uuid, + #[serde(rename = "uuid")] + pub aci: Uuid, pub pni: Uuid, pub storage_capable: bool, #[serde(default)] @@ -1287,8 +1288,8 @@ pub trait PushService: MaybeSend { registration_method: RegistrationMethod<'a>, account_attributes: AccountAttributes, skip_device_transfer: bool, - aci_identity_key: IdentityKey, - pni_identity_key: IdentityKey, + aci_identity_key: &IdentityKey, + pni_identity_key: &IdentityKey, device_activation_request: DeviceActivationRequest, ) -> Result { #[derive(serde::Serialize, Debug)] diff --git a/libsignal-service/src/sender.rs b/libsignal-service/src/sender.rs index 53ad9c699..8ebbdf43d 100644 --- a/libsignal-service/src/sender.rs +++ b/libsignal-service/src/sender.rs @@ -137,8 +137,8 @@ where cipher: ServiceCipher, csprng: R, protocol_store: S, - local_aci: ServiceAddress, - local_pni: ServiceAddress, + local_aci: impl Into, + local_pni: impl Into, aci_identity: IdentityKeyPair, pni_identity: Option, device_id: DeviceId, @@ -150,8 +150,8 @@ where cipher, csprng, protocol_store, - local_aci, - local_pni, + local_aci: local_aci.into(), + local_pni: local_pni.into(), aci_identity, pni_identity, device_id, diff --git a/libsignal-service/src/session_store.rs b/libsignal-service/src/session_store.rs index e203807c8..affbff09b 100644 --- a/libsignal-service/src/session_store.rs +++ b/libsignal-service/src/session_store.rs @@ -1,3 +1,4 @@ +use async_trait::async_trait; use libsignal_protocol::{ProtocolAddress, SessionStore, SignalProtocolError}; use crate::{push_service::DEFAULT_DEVICE_ID, ServiceAddress}; @@ -5,8 +6,7 @@ use crate::{push_service::DEFAULT_DEVICE_ID, ServiceAddress}; /// This is additional functions required to handle /// session deletion. It might be a candidate for inclusion into /// the bigger `SessionStore` trait. -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] +#[async_trait(?Send)] pub trait SessionStoreExt: SessionStore { /// Get the IDs of all known sub devices with active sessions for a recipient. /// @@ -48,46 +48,36 @@ pub trait SessionStoreExt: SessionStore { Ok(count) } - // #[async_trait] sadly doesn't work here, - // because calls to libsignal_protocol are unsend. - fn compute_safety_number<'s>( + async fn compute_safety_number<'s>( &'s self, local_address: &'s ServiceAddress, address: &'s ServiceAddress, - ) -> std::pin::Pin< - Box< - dyn std::future::Future< - Output = Result, - > + 's, - >, - > + ) -> Result where Self: Sized + libsignal_protocol::IdentityKeyStore, { - Box::pin(async move { - let addr = crate::cipher::get_preferred_protocol_address( - self, - address, - DEFAULT_DEVICE_ID.into(), - ) - .await?; - let ident = self - .get_identity(&addr) - .await? - .ok_or(SignalProtocolError::UntrustedIdentity(addr))?; - let local = self - .get_identity_key_pair() - .await - .expect("valid local identity"); - let fp = libsignal_protocol::Fingerprint::new( - 2, - 5200, - local_address.uuid.as_bytes(), - local.identity_key(), - address.uuid.as_bytes(), - &ident, - )?; - fp.display_string() - }) + let addr = crate::cipher::get_preferred_protocol_address( + self, + address, + DEFAULT_DEVICE_ID.into(), + ) + .await?; + let ident = self + .get_identity(&addr) + .await? + .ok_or(SignalProtocolError::UntrustedIdentity(addr))?; + let local = self + .get_identity_key_pair() + .await + .expect("valid local identity"); + let fp = libsignal_protocol::Fingerprint::new( + 2, + 5200, + local_address.uuid.as_bytes(), + local.identity_key(), + address.uuid.as_bytes(), + &ident, + )?; + fp.display_string() } } diff --git a/libsignal-service/src/utils.rs b/libsignal-service/src/utils.rs index 00f6242b6..236b6968b 100644 --- a/libsignal-service/src/utils.rs +++ b/libsignal-service/src/utils.rs @@ -85,14 +85,14 @@ pub mod serde_optional_base64 { } } -pub mod serde_public_key { +pub mod serde_identity_key { use super::BASE64_RELAXED; use base64::prelude::*; - use libsignal_protocol::PublicKey; + use libsignal_protocol::IdentityKey; use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize( - public_key: &PublicKey, + public_key: &IdentityKey, serializer: S, ) -> Result where @@ -102,11 +102,11 @@ pub mod serde_public_key { serializer.serialize_str(&BASE64_RELAXED.encode(&public_key)) } - pub fn deserialize<'de, D>(deserializer: D) -> Result + pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - PublicKey::deserialize( + IdentityKey::decode( &BASE64_RELAXED .decode(String::deserialize(deserializer)?) .map_err(serde::de::Error::custom)?, @@ -115,16 +115,16 @@ pub mod serde_public_key { } } -pub mod serde_optional_public_key { +pub mod serde_optional_identity_key { use super::BASE64_RELAXED; use base64::prelude::*; - use libsignal_protocol::PublicKey; + use libsignal_protocol::IdentityKey; use serde::{Deserialize, Deserializer, Serializer}; - use super::serde_public_key; + use super::serde_identity_key; pub fn serialize( - public_key: &Option, + public_key: &Option, serializer: S, ) -> Result where @@ -132,7 +132,7 @@ pub mod serde_optional_public_key { { match public_key { Some(public_key) => { - serde_public_key::serialize(public_key, serializer) + serde_identity_key::serialize(public_key, serializer) }, None => serializer.serialize_none(), } @@ -140,13 +140,13 @@ pub mod serde_optional_public_key { pub fn deserialize<'de, D>( deserializer: D, - ) -> Result, D::Error> + ) -> Result, D::Error> where D: Deserializer<'de>, { match Option::::deserialize(deserializer)? { Some(public_key) => Ok(Some( - PublicKey::deserialize( + IdentityKey::decode( &BASE64_RELAXED .decode(public_key) .map_err(serde::de::Error::custom)?,