libsignal_service/websocket/
keys.rs1use std::collections::HashMap;
2
3use libsignal_core::DeviceId;
4use libsignal_protocol::{
5 kem::{Key, Public},
6 IdentityKey, PreKeyBundle, PublicKey, SenderCertificate, ServiceId,
7 ServiceIdKind, SignalProtocolError,
8};
9use reqwest::Method;
10use serde::Deserialize;
11
12use crate::{
13 pre_keys::{
14 KyberPreKeyEntity, PreKeyEntity, PreKeyState, SignedPreKeyEntity,
15 },
16 push_service::response::SignalServiceResponse,
17 push_service::DEFAULT_DEVICE_ID,
18 sender::OutgoingPushMessage,
19 utils::{serde_base64, serde_device_id},
20 websocket::{self, registration::VerifyAccountResponse, SignalWebSocket},
21};
22
23use super::ServiceError;
24
25#[derive(Debug, Deserialize, Default)]
26#[serde(rename_all = "camelCase")]
27pub struct PreKeyStatus {
28 pub count: u32,
29 pub pq_count: u32,
30}
31
32#[derive(Debug, Deserialize)]
33#[serde(rename_all = "camelCase")]
34pub struct PreKeyResponse {
35 #[serde(with = "serde_base64")]
36 pub identity_key: Vec<u8>,
37 pub devices: Vec<PreKeyResponseItem>,
38}
39
40#[derive(Debug, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct PreKeyResponseItem {
43 #[serde(with = "serde_device_id")]
44 pub device_id: DeviceId,
45 pub registration_id: u32,
46 pub signed_pre_key: SignedPreKeyEntity,
47 pub pre_key: Option<PreKeyEntity>,
48 pub pq_pre_key: KyberPreKeyEntity,
49}
50
51impl PreKeyResponseItem {
52 pub(crate) fn into_bundle(
53 self,
54 identity: IdentityKey,
55 ) -> Result<PreKeyBundle, ServiceError> {
56 let pre_key_bundle = PreKeyBundle::new(
57 self.registration_id,
58 self.device_id,
59 self.pre_key
60 .map(|pk| -> Result<_, SignalProtocolError> {
61 Ok((
62 pk.key_id.into(),
63 PublicKey::deserialize(&pk.public_key)?,
64 ))
65 })
66 .transpose()?,
67 self.signed_pre_key.key_id.into(),
69 PublicKey::deserialize(&self.signed_pre_key.public_key)?,
70 self.signed_pre_key.signature,
71 self.pq_pre_key.key_id.into(),
72 Key::<Public>::deserialize(&self.pq_pre_key.public_key)?,
73 self.pq_pre_key.signature,
74 identity,
75 )?;
76
77 Ok(pre_key_bundle)
78 }
79}
80
81#[derive(Debug, Deserialize)]
82#[serde(rename_all = "camelCase")]
83struct SenderCertificateJson {
84 #[serde(with = "serde_base64")]
85 certificate: Vec<u8>,
86}
87
88impl SignalWebSocket<websocket::Identified> {
89 pub async fn get_pre_key_status(
90 &mut self,
91 service_id_kind: ServiceIdKind,
92 ) -> Result<PreKeyStatus, ServiceError> {
93 self.http_request(
94 Method::GET,
95 format!("/v2/keys?identity={}", service_id_kind),
96 )?
97 .send()
98 .await?
99 .service_error_for_status()
100 .await?
101 .json()
102 .await
103 }
104
105 pub async fn check_pre_keys(
115 &mut self,
116 service_id_kind: ServiceIdKind,
117 digest: &[u8; 32],
118 ) -> Result<bool, ServiceError> {
119 #[derive(serde::Serialize)]
120 #[serde(rename_all = "camelCase")]
121 struct CheckPreKeysRequest<'a> {
122 identity_type: String,
123 #[serde(with = "serde_base64")]
124 digest: &'a [u8; 32],
125 }
126
127 let req = CheckPreKeysRequest {
128 identity_type: service_id_kind.to_string(),
129 digest,
130 };
131
132 let res = self
133 .http_request(Method::POST, "/v2/keys/check")?
134 .send_json(&req)
135 .await?;
136
137 if res.status_code() == Some(reqwest::StatusCode::CONFLICT) {
138 return Ok(false);
139 }
140
141 res.service_error_for_status().await?;
142
143 Ok(true)
144 }
145
146 pub async fn register_pre_keys(
147 &mut self,
148 service_id_kind: ServiceIdKind,
149 pre_key_state: PreKeyState,
150 ) -> Result<(), ServiceError> {
151 self.http_request(
152 Method::PUT,
153 format!("/v2/keys?identity={}", service_id_kind),
154 )?
155 .send_json(&pre_key_state)
156 .await?
157 .service_error_for_status()
158 .await?;
159
160 Ok(())
161 }
162
163 pub async fn get_pre_key(
164 &mut self,
165 destination: &ServiceId,
166 device_id: DeviceId,
167 ) -> Result<PreKeyBundle, ServiceError> {
168 let path = format!(
169 "/v2/keys/{}/{}",
170 destination.service_id_string(),
171 device_id
172 );
173
174 let mut pre_key_response: PreKeyResponse = self
175 .http_request(Method::GET, path)?
176 .send()
177 .await?
178 .service_error_for_status()
179 .await?
180 .json()
181 .await?;
182
183 assert!(!pre_key_response.devices.is_empty());
184
185 let identity = IdentityKey::decode(&pre_key_response.identity_key)?;
186 let device = pre_key_response.devices.remove(0);
187 device.into_bundle(identity)
188 }
189
190 pub(crate) async fn get_pre_keys(
191 &mut self,
192 destination: &ServiceId,
193 device_id: DeviceId,
194 ) -> Result<Vec<PreKeyBundle>, ServiceError> {
195 let path = if device_id == *DEFAULT_DEVICE_ID {
196 format!("/v2/keys/{}/*", destination.service_id_string())
197 } else {
198 format!(
199 "/v2/keys/{}/{}",
200 destination.service_id_string(),
201 device_id
202 )
203 };
204 let pre_key_response: PreKeyResponse = self
205 .http_request(Method::GET, path)?
206 .send()
207 .await?
208 .service_error_for_status()
209 .await?
210 .json()
211 .await?;
212 let mut pre_keys = vec![];
213 let identity = IdentityKey::decode(&pre_key_response.identity_key)?;
214 for device in pre_key_response.devices {
215 pre_keys.push(device.into_bundle(identity)?);
216 }
217 Ok(pre_keys)
218 }
219
220 pub async fn get_sender_certificate(
221 &mut self,
222 ) -> Result<SenderCertificate, ServiceError> {
223 let cert: SenderCertificateJson = self
224 .http_request(Method::GET, "/v1/certificate/delivery")?
225 .send()
226 .await?
227 .service_error_for_status()
228 .await?
229 .json()
230 .await?;
231 Ok(SenderCertificate::deserialize(&cert.certificate)?)
232 }
233
234 pub async fn get_uuid_only_sender_certificate(
235 &mut self,
236 ) -> Result<SenderCertificate, ServiceError> {
237 let cert: SenderCertificateJson = self
238 .http_request(
239 Method::GET,
240 "/v1/certificate/delivery?includeE164=false",
241 )?
242 .send()
243 .await?
244 .service_error_for_status()
245 .await?
246 .json()
247 .await?;
248 Ok(SenderCertificate::deserialize(&cert.certificate)?)
249 }
250
251 pub async fn distribute_pni_keys(
252 &mut self,
253 pni_identity_key: &IdentityKey,
254 device_messages: Vec<OutgoingPushMessage>,
255 device_pni_signed_prekeys: HashMap<String, SignedPreKeyEntity>,
256 device_pni_last_resort_kyber_prekeys: HashMap<
257 String,
258 KyberPreKeyEntity,
259 >,
260 pni_registration_ids: HashMap<String, u32>,
261 signature_valid_on_each_signed_pre_key: bool,
262 ) -> Result<VerifyAccountResponse, ServiceError> {
263 #[derive(serde::Serialize, Debug)]
264 #[serde(rename_all = "camelCase")]
265 struct PniKeyDistributionRequest {
266 #[serde(with = "serde_base64")]
267 pni_identity_key: Vec<u8>,
268 device_messages: Vec<OutgoingPushMessage>,
269 device_pni_signed_prekeys: HashMap<String, SignedPreKeyEntity>,
270 #[serde(rename = "devicePniPqLastResortPrekeys")]
271 device_pni_last_resort_kyber_prekeys:
272 HashMap<String, KyberPreKeyEntity>,
273 pni_registration_ids: HashMap<String, u32>,
274 signature_valid_on_each_signed_pre_key: bool,
275 }
276 self.http_request(
277 Method::PUT,
278 "/v2/accounts/phone_number_identity_key_distribution",
279 )?
280 .send_json(&PniKeyDistributionRequest {
281 pni_identity_key: pni_identity_key.serialize().into(),
282 device_messages,
283 device_pni_signed_prekeys,
284 device_pni_last_resort_kyber_prekeys,
285 pni_registration_ids,
286 signature_valid_on_each_signed_pre_key,
287 })
288 .await?
289 .service_error_for_status()
290 .await?
291 .json()
292 .await
293 }
294}