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