-
Notifications
You must be signed in to change notification settings - Fork 0
/
encrypted.rs
55 lines (42 loc) · 2 KB
/
encrypted.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use anyhow::anyhow;
use sodiumoxide::crypto::box_::{gen_nonce, open_precomputed, seal_precomputed, Nonce};
use tracing::info;
use crate::{client::CharacteristicClient, command::Command, pairing::AuthInfo};
pub struct AuthenticatedClient {
auth_info: AuthInfo,
client: CharacteristicClient,
}
impl AuthenticatedClient {
pub fn new(auth_info: AuthInfo, client: CharacteristicClient) -> Self {
Self { auth_info, client }
}
pub async fn write(&self, command: Command) -> Result<(), anyhow::Error> {
let payload = command.into_bytes_with_auth(self.auth_info.authorization_id);
info!("sending plaintext: {:02X?}", payload);
let nonce = gen_nonce();
let ciphertext = seal_precomputed(&payload, &nonce, &self.auth_info.shared_key);
let mut message = Vec::new();
message.extend_from_slice(nonce.as_ref());
message.extend_from_slice(&self.auth_info.authorization_id.to_le_bytes());
let ciphertext_len = (ciphertext.len() as u16).to_le_bytes();
message.extend_from_slice(&ciphertext_len);
message.extend_from_slice(&ciphertext);
info!("sending full message: {:02X?}", message);
self.client.write_raw(message).await?;
Ok(())
}
pub async fn receive(&mut self) -> Result<Command, anyhow::Error> {
let encrypted_bytes = self.client.receive_raw().await?;
if encrypted_bytes.len() < 30 {
return Err(anyhow!("Invalid length"));
}
let (nonce, encrypted_bytes) = encrypted_bytes.split_at(24);
let (_, encrypted_bytes) = encrypted_bytes.split_at(6);
let nonce = Nonce::from_slice(nonce).ok_or_else(|| anyhow!("Invalid nonce"))?;
let decrypted_bytes = open_precomputed(encrypted_bytes, &nonce, &self.auth_info.shared_key)
.map_err(|_| anyhow!("Failed to decrypt message"))?;
info!("received plaintext: {:02X?}", decrypted_bytes);
let (cmd, _auth_id) = Command::parse_with_auth(&decrypted_bytes)?;
Ok(cmd)
}
}