diff --git a/libsignal-service-hyper/examples/registering.rs b/libsignal-service-hyper/examples/registering.rs index 8789e9989..c4b008eb1 100644 --- a/libsignal-service-hyper/examples/registering.rs +++ b/libsignal-service-hyper/examples/registering.rs @@ -2,12 +2,13 @@ use std::str::FromStr; use libsignal_service::configuration::{ServiceCredentials, SignalServers}; use libsignal_service::prelude::phonenumber::PhoneNumber; +use libsignal_service::prelude::ProfileKey; use libsignal_service::provisioning::{ generate_registration_id, ProvisioningManager, VerificationCodeResponse, VerifyAccountResponse, }; use libsignal_service::push_service::{ - AccountAttributes, DeviceCapabilities, ProfileKey, PushService, + AccountAttributes, DeviceCapabilities, ProfileKeyExt, PushService, ServiceError, }; use libsignal_service::USER_AGENT; @@ -81,7 +82,7 @@ async fn confirm_registration<'a, T: PushService>( let signaling_key = generate_signaling_key(); let mut profile_key = [0u8; 32]; rand::thread_rng().fill_bytes(&mut profile_key); - let profile_key = ProfileKey(profile_key); + let profile_key = ProfileKey::create(profile_key); manager .confirm_verification_code( diff --git a/libsignal-service/src/account_manager.rs b/libsignal-service/src/account_manager.rs index 973ce4fa6..1afceed62 100644 --- a/libsignal-service/src/account_manager.rs +++ b/libsignal-service/src/account_manager.rs @@ -31,7 +31,7 @@ use crate::{ pub struct AccountManager { service: Service, - profile_key: Option<[u8; 32]>, + profile_key: Option, } #[derive(thiserror::Error, Debug)] @@ -68,7 +68,7 @@ const PRE_KEY_BATCH_SIZE: u32 = 100; const PRE_KEY_MEDIUM_MAX_VALUE: u32 = 0xFFFFFF; impl AccountManager { - pub fn new(service: Service, profile_key: Option<[u8; 32]>) -> Self { + pub fn new(service: Service, profile_key: Option) -> Self { Self { service, profile_key, @@ -273,7 +273,7 @@ impl AccountManager { pni_identity_key_public: None, pni_identity_key_private: None, pni: None, - profile_key: self.profile_key.as_ref().map(|x| x.to_vec()), + profile_key: self.profile_key.as_ref().map(|x| x.bytes.to_vec()), // CURRENT is not exposed by prost :( provisioning_version: Some(i32::from( ProvisioningVersion::TabletSupport, @@ -330,7 +330,6 @@ impl AccountManager { ) -> Result { let profile_key = self.profile_key.expect("set profile key in AccountManager"); - let profile_key = ProfileKey::create(profile_key); let encrypted_profile = self .service @@ -360,7 +359,6 @@ impl AccountManager { ) -> Result, ProfileManagerError> { let profile_key = self.profile_key.expect("set profile key in AccountManager"); - let profile_key = ProfileKey::create(profile_key); let profile_cipher = ProfileCipher::from(profile_key); // Profile encryption diff --git a/libsignal-service/src/lib.rs b/libsignal-service/src/lib.rs index 6f07d92fa..62d83f88e 100644 --- a/libsignal-service/src/lib.rs +++ b/libsignal-service/src/lib.rs @@ -81,7 +81,10 @@ pub mod prelude { pub use phonenumber; pub use prost::Message as ProtobufMessage; pub use uuid::{Error as UuidError, Uuid}; - pub use zkgroup::groups::{GroupMasterKey, GroupSecretParams}; + pub use zkgroup::{ + groups::{GroupMasterKey, GroupSecretParams}, + profiles::ProfileKey, + }; pub mod protocol { pub use crate::session_store::SessionStoreExt; diff --git a/libsignal-service/src/models.rs b/libsignal-service/src/models.rs index 5246841b3..72feb2f70 100644 --- a/libsignal-service/src/models.rs +++ b/libsignal-service/src/models.rs @@ -1,8 +1,11 @@ +use std::convert::TryInto; + use crate::{proto::Verified, ParseServiceAddressError, ServiceAddress}; use bytes::Bytes; use serde::{Deserialize, Serialize}; use thiserror::Error; +use zkgroup::profiles::ProfileKey; /// Attachment represents an attachment received from a peer #[derive(Debug, Serialize, Deserialize)] @@ -75,4 +78,13 @@ impl Contact { }), }) } + + pub fn profile_key(&self) -> Result { + Ok(ProfileKey::create( + self.profile_key + .clone() + .try_into() + .map_err(|_| ParseContactError::MissingProfileKey)?, + )) + } } diff --git a/libsignal-service/src/push_service.rs b/libsignal-service/src/push_service.rs index 1b4a9ce88..999d2d517 100644 --- a/libsignal-service/src/push_service.rs +++ b/libsignal-service/src/push_service.rs @@ -1,4 +1,4 @@ -use std::{convert::TryInto, fmt, ops::Deref, time::Duration}; +use std::{fmt, time::Duration}; use crate::{ configuration::{Endpoint, ServiceCredentials}, @@ -24,7 +24,7 @@ use libsignal_protocol::{ use prost::Message as ProtobufMessage; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use zkgroup::profiles::{ProfileKeyCommitment, ProfileKeyVersion}; +use zkgroup::profiles::{ProfileKey, ProfileKeyCommitment, ProfileKeyVersion}; /** Since we can't use format!() with constants, the URLs here are just for reference purposes @@ -135,9 +135,6 @@ pub struct ProofRequired { pub options: Vec, } -#[derive(Clone)] -pub struct ProfileKey(pub [u8; 32]); - #[derive(Debug, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct PreKeyStatus { @@ -170,9 +167,13 @@ impl fmt::Debug for HttpAuth { } } -impl ProfileKey { - pub fn derive_access_key(&self) -> Vec { - let key = GenericArray::from_slice(&self.0); +pub trait ProfileKeyExt { + fn derive_access_key(&self) -> Vec; +} + +impl ProfileKeyExt for ProfileKey { + fn derive_access_key(&self) -> Vec { + let key = GenericArray::from_slice(&self.bytes); let cipher = Aes256Gcm::new(key); let nonce = GenericArray::from_slice(&[0u8; 12]); let buf = [0u8; 16]; @@ -182,42 +183,6 @@ impl ProfileKey { } } -impl Deref for ProfileKey { - type Target = [u8; 32]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Serialize for ProfileKey { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&base64::encode(self.0)) - } -} - -impl<'de> Deserialize<'de> for ProfileKey { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - Ok(ProfileKey( - base64::decode(String::deserialize(deserializer)?) - .map_err(serde::de::Error::custom)? - .try_into() - .map_err(|buf: Vec| { - serde::de::Error::invalid_length( - buf.len(), - &"invalid profile key length", - ) - })?, - )) - } -} - #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PreKeyResponse {