interop/clients/cryptobox/
native.rs1use crate::clients::{EmulatedClient, EmulatedClientProtocol, EmulatedClientType, EmulatedProteusClient};
18use color_eyre::eyre::{Result, eyre};
19use std::cell::Cell;
20
21pub(crate) struct CryptoboxNativeClient {
22 client_id: Vec<u8>,
23 last_prekey_id: Cell<u16>,
24 cbox: Option<cryptobox::CBox<cryptobox::store::file::FileStore>>,
25 tempdir: Option<tempfile::TempDir>,
26}
27
28impl CryptoboxNativeClient {
29 pub(crate) fn new() -> Self {
30 let client_id = uuid::Uuid::new_v4().into_bytes().to_vec();
31 Self {
32 client_id,
33 last_prekey_id: Cell::new(0),
34 cbox: None,
35 tempdir: None,
36 }
37 }
38}
39
40#[async_trait::async_trait(?Send)]
41impl EmulatedClient for CryptoboxNativeClient {
42 fn client_name(&self) -> &str {
43 "Cryptobox::native"
44 }
45
46 fn client_type(&self) -> EmulatedClientType {
47 EmulatedClientType::Native
48 }
49
50 fn client_id(&self) -> &[u8] {
51 &self.client_id
52 }
53
54 fn client_protocol(&self) -> EmulatedClientProtocol {
55 EmulatedClientProtocol::PROTEUS
56 }
57
58 async fn wipe(mut self) -> Result<()> {
59 let _ = self.cbox.take();
60 if let Some(tempdir) = self.tempdir.take() {
61 tempdir.close()?;
62 }
63
64 Ok(())
65 }
66}
67
68#[async_trait::async_trait(?Send)]
69impl EmulatedProteusClient for CryptoboxNativeClient {
70 async fn init(&mut self) -> Result<()> {
71 let tempdir = tempfile::tempdir()?;
72 self.cbox = Some(cryptobox::CBox::file_open(tempdir.path())?);
73 self.tempdir = Some(tempdir);
74 Ok(())
75 }
76
77 async fn get_prekey(&self) -> Result<Vec<u8>> {
78 let cbox = self.cbox.as_ref().ok_or(eyre!("Cryptobox isn't initialized"))?;
79 self.last_prekey_id.replace(self.last_prekey_id.get() + 1);
80 let prekey_bundle = cbox.new_prekey(proteus::keys::PreKeyId::new(self.last_prekey_id.get()))?;
81 Ok(prekey_bundle.serialise()?)
82 }
83
84 async fn session_from_prekey(&self, session_id: &str, prekey: &[u8]) -> Result<()> {
85 let cbox = self.cbox.as_ref().ok_or(eyre!("Cryptobox isn't initialized"))?;
86 let mut session = cbox.session_from_prekey(session_id.to_string(), prekey)?;
87 cbox.session_save(&mut session)?;
88 Ok(())
89 }
90
91 async fn session_from_message(&self, session_id: &str, message: &[u8]) -> Result<Vec<u8>> {
92 let cbox = self.cbox.as_ref().ok_or(eyre!("Cryptobox isn't initialized"))?;
93 let (mut session, message) = cbox.session_from_message(session_id.to_string(), message)?;
94 cbox.session_save(&mut session)?;
95 Ok(message)
96 }
97
98 async fn encrypt(&self, session_id: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
99 let cbox = self.cbox.as_ref().ok_or(eyre!("Cryptobox isn't initialized"))?;
100 let mut session = cbox
101 .session_load(session_id.to_string())?
102 .ok_or(eyre!("session not found"))?;
103 let encrypted = session.encrypt(plaintext)?;
104 cbox.session_save(&mut session)?;
105 Ok(encrypted)
106 }
107
108 async fn decrypt(&self, session_id: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
109 let cbox = self.cbox.as_ref().ok_or(eyre!("Cryptobox isn't initialized"))?;
110 let mut session = cbox
111 .session_load(session_id.to_string())?
112 .ok_or(eyre!("session not found"))?;
113 let decrypted = session.decrypt(ciphertext)?;
114 cbox.session_save(&mut session)?;
115 Ok(decrypted)
116 }
117
118 async fn fingerprint(&self) -> Result<String> {
119 self.cbox
120 .as_ref()
121 .map(|cbox| cbox.fingerprint())
122 .ok_or(eyre!("Cryptobox isn't initialized"))
123 }
124}