libsignal_service/push_service/
keys.rs

1use std::collections::HashMap;
2
3use libsignal_protocol::{
4    IdentityKey, PreKeyBundle, SenderCertificate, ServiceId, ServiceIdKind,
5};
6use reqwest::Method;
7use serde::Deserialize;
8
9use crate::{
10    configuration::Endpoint,
11    pre_keys::{KyberPreKeyEntity, PreKeyState, SignedPreKeyEntity},
12    push_service::PreKeyResponse,
13    sender::OutgoingPushMessage,
14    utils::serde_base64,
15};
16
17use super::{
18    response::ReqwestExt, HttpAuthOverride, PushService, SenderCertificateJson,
19    ServiceError, VerifyAccountResponse,
20};
21
22#[derive(Debug, Deserialize, Default)]
23#[serde(rename_all = "camelCase")]
24pub struct PreKeyStatus {
25    pub count: u32,
26    pub pq_count: u32,
27}
28
29impl PushService {
30    pub async fn get_pre_key_status(
31        &mut self,
32        service_id_kind: ServiceIdKind,
33    ) -> Result<PreKeyStatus, ServiceError> {
34        self.request(
35            Method::GET,
36            Endpoint::service(format!("/v2/keys?identity={}", service_id_kind)),
37            HttpAuthOverride::NoOverride,
38        )?
39        .send()
40        .await?
41        .service_error_for_status()
42        .await?
43        .json()
44        .await
45        .map_err(Into::into)
46    }
47
48    /// Checks for consistency of the repeated-use keys
49    ///
50    /// Supply the digest as follows:
51    /// `SHA256(identityKeyBytes || signedEcPreKeyId || signedEcPreKeyIdBytes || lastResortKeyId ||
52    /// lastResortKeyBytes)`
53    ///
54    /// The IDs are represented as 8-byte big endian ints.
55    ///
56    /// Retuns `Ok(true)` if the view is consistent, `Ok(false)` if the view is inconsistent.
57    pub async fn check_pre_keys(
58        &mut self,
59        service_id_kind: ServiceIdKind,
60        digest: &[u8; 32],
61    ) -> Result<bool, ServiceError> {
62        #[derive(serde::Serialize)]
63        #[serde(rename_all = "camelCase")]
64        struct CheckPreKeysRequest<'a> {
65            identity_type: String,
66            #[serde(with = "serde_base64")]
67            digest: &'a [u8; 32],
68        }
69
70        let req = CheckPreKeysRequest {
71            identity_type: service_id_kind.to_string(),
72            digest,
73        };
74
75        let res = self
76            .request(
77                Method::POST,
78                Endpoint::service("/v2/keys/check"),
79                HttpAuthOverride::NoOverride,
80            )?
81            .json(&req)
82            .send()
83            .await?;
84
85        if res.status() == reqwest::StatusCode::CONFLICT {
86            return Ok(false);
87        }
88
89        res.service_error_for_status().await?;
90
91        Ok(true)
92    }
93
94    pub async fn register_pre_keys(
95        &mut self,
96        service_id_kind: ServiceIdKind,
97        pre_key_state: PreKeyState,
98    ) -> Result<(), ServiceError> {
99        self.request(
100            Method::PUT,
101            Endpoint::service(format!("/v2/keys?identity={}", service_id_kind)),
102            HttpAuthOverride::NoOverride,
103        )?
104        .json(&pre_key_state)
105        .send()
106        .await?
107        .service_error_for_status()
108        .await?;
109
110        Ok(())
111    }
112
113    pub async fn get_pre_key(
114        &mut self,
115        destination: &ServiceId,
116        device_id: u32,
117    ) -> Result<PreKeyBundle, ServiceError> {
118        let path = format!(
119            "/v2/keys/{}/{}",
120            destination.service_id_string(),
121            device_id
122        );
123
124        let mut pre_key_response: PreKeyResponse = self
125            .request(
126                Method::GET,
127                Endpoint::service(path),
128                HttpAuthOverride::NoOverride,
129            )?
130            .send()
131            .await?
132            .service_error_for_status()
133            .await?
134            .json()
135            .await?;
136
137        assert!(!pre_key_response.devices.is_empty());
138
139        let identity = IdentityKey::decode(&pre_key_response.identity_key)?;
140        let device = pre_key_response.devices.remove(0);
141        Ok(device.into_bundle(identity)?)
142    }
143
144    pub(crate) async fn get_pre_keys(
145        &mut self,
146        destination: &ServiceId,
147        device_id: u32,
148    ) -> Result<Vec<PreKeyBundle>, ServiceError> {
149        let path = if device_id == 1 {
150            format!("/v2/keys/{}/*", destination.service_id_string())
151        } else {
152            format!(
153                "/v2/keys/{}/{}",
154                destination.service_id_string(),
155                device_id
156            )
157        };
158        let pre_key_response: PreKeyResponse = self
159            .request(
160                Method::GET,
161                Endpoint::service(path),
162                HttpAuthOverride::NoOverride,
163            )?
164            .send()
165            .await?
166            .service_error_for_status()
167            .await?
168            .json()
169            .await?;
170        let mut pre_keys = vec![];
171        let identity = IdentityKey::decode(&pre_key_response.identity_key)?;
172        for device in pre_key_response.devices {
173            pre_keys.push(device.into_bundle(identity)?);
174        }
175        Ok(pre_keys)
176    }
177
178    pub async fn get_sender_certificate(
179        &mut self,
180    ) -> Result<SenderCertificate, ServiceError> {
181        let cert: SenderCertificateJson = self
182            .request(
183                Method::GET,
184                Endpoint::service("/v1/certificate/delivery"),
185                HttpAuthOverride::NoOverride,
186            )?
187            .send()
188            .await?
189            .service_error_for_status()
190            .await?
191            .json()
192            .await?;
193        Ok(SenderCertificate::deserialize(&cert.certificate)?)
194    }
195
196    pub async fn get_uuid_only_sender_certificate(
197        &mut self,
198    ) -> Result<SenderCertificate, ServiceError> {
199        let cert: SenderCertificateJson = self
200            .request(
201                Method::GET,
202                Endpoint::service("/v1/certificate/delivery?includeE164=false"),
203                HttpAuthOverride::NoOverride,
204            )?
205            .send()
206            .await?
207            .service_error_for_status()
208            .await?
209            .json()
210            .await?;
211        Ok(SenderCertificate::deserialize(&cert.certificate)?)
212    }
213
214    pub async fn distribute_pni_keys(
215        &mut self,
216        pni_identity_key: &IdentityKey,
217        device_messages: Vec<OutgoingPushMessage>,
218        device_pni_signed_prekeys: HashMap<String, SignedPreKeyEntity>,
219        device_pni_last_resort_kyber_prekeys: HashMap<
220            String,
221            KyberPreKeyEntity,
222        >,
223        pni_registration_ids: HashMap<String, u32>,
224        signature_valid_on_each_signed_pre_key: bool,
225    ) -> Result<VerifyAccountResponse, ServiceError> {
226        #[derive(serde::Serialize, Debug)]
227        #[serde(rename_all = "camelCase")]
228        struct PniKeyDistributionRequest {
229            #[serde(with = "serde_base64")]
230            pni_identity_key: Vec<u8>,
231            device_messages: Vec<OutgoingPushMessage>,
232            device_pni_signed_prekeys: HashMap<String, SignedPreKeyEntity>,
233            #[serde(rename = "devicePniPqLastResortPrekeys")]
234            device_pni_last_resort_kyber_prekeys:
235                HashMap<String, KyberPreKeyEntity>,
236            pni_registration_ids: HashMap<String, u32>,
237            signature_valid_on_each_signed_pre_key: bool,
238        }
239        self.request(
240            Method::PUT,
241            Endpoint::service(
242                "/v2/accounts/phone_number_identity_key_distribution",
243            ),
244            HttpAuthOverride::NoOverride,
245        )?
246        .json(&PniKeyDistributionRequest {
247            pni_identity_key: pni_identity_key.serialize().into(),
248            device_messages,
249            device_pni_signed_prekeys,
250            device_pni_last_resort_kyber_prekeys,
251            pni_registration_ids,
252            signature_valid_on_each_signed_pre_key,
253        })
254        .send()
255        .await?
256        .service_error_for_status()
257        .await?
258        .json()
259        .await
260        .map_err(Into::into)
261    }
262}