client_core/
key_exchange.rs1use crate::crypto;
8use crate::http::RestClient;
9use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
10
11#[derive(Debug, thiserror::Error)]
12pub enum RespondError {
13 #[error("derive shared key: {0}")]
14 DeriveShared(String),
15 #[error("encrypt user key: {0}")]
16 Encrypt(String),
17 #[error("post bundle: {0}")]
18 Post(#[from] crate::http::HttpError),
19}
20
21pub async fn respond(
27 client: &RestClient,
28 target_device_id: &str,
29 peer_pub_b64: &str,
30 user_master_key_b64: &str,
31) -> Result<(), RespondError> {
32 let (eph_priv_b64, eph_pub_b64) = crypto::generate_ephemeral_keypair();
33
34 let shared = crypto::derive_shared_key(&eph_priv_b64, peer_pub_b64)
35 .map_err(RespondError::DeriveShared)?;
36
37 let raw_master = URL_SAFE_NO_PAD
38 .decode(user_master_key_b64)
39 .map_err(|e| RespondError::Encrypt(format!("master key decode: {}", e)))?;
40
41 let encrypted = crypto::encrypt(&shared, &raw_master).map_err(RespondError::Encrypt)?;
42
43 client
44 .post_key_bundle(target_device_id, &eph_pub_b64, &encrypted)
45 .await?;
46 Ok(())
47}