1#![doc=include_str!("../../doc/user.md")]
2#![doc=include_str!("../../doc/encrypt_user.md")]
3#![doc=include_str!("../../doc/file.md")]
4
5pub mod crypto_sync;
6mod export;
7#[cfg(feature = "file")]
8pub mod file;
9#[cfg(feature = "network")]
10pub mod net;
11
12use std::marker::PhantomData;
13
14use sentc_crypto::entities::user::{UserDataInt, UserKeyDataInt};
15use sentc_crypto::group::Group as SdkGroup;
16use sentc_crypto::sdk_common::group::GroupHmacData;
17use sentc_crypto::sdk_common::user::{UserPublicKeyData, UserVerifyKeyData};
18use sentc_crypto::sdk_common::{DeviceId, SymKeyId, UserId};
19use sentc_crypto::sdk_core::cryptomat::{PwHash, SearchableKeyGen, SortableKeyGen};
20use sentc_crypto::sdk_utils::cryptomat::{
21 PkFromUserKeyWrapper,
22 SearchableKeyComposerWrapper,
23 SignComposerWrapper,
24 SignKeyPairWrapper,
25 SortableKeyComposerWrapper,
26 StaticKeyComposerWrapper,
27 StaticKeyPairWrapper,
28 SymKeyComposerWrapper,
29 SymKeyGenWrapper,
30 SymKeyWrapper,
31 VerifyKFromUserKeyWrapper,
32};
33use sentc_crypto::user::{generate_user_register_data, User as SdkUser};
34
35use crate::error::SentcError;
36use crate::group::prepare_group_keys_ref;
37use crate::KeyMap;
38
39pub struct User<SGen, StGen, SignGen, SearchGen, SortGen, SC, StC, SignC, SearchC, SortC, PC, VC, PwH>
43where
44 SGen: SymKeyGenWrapper,
45 StGen: StaticKeyPairWrapper,
46 SignGen: SignKeyPairWrapper,
47 SearchGen: SearchableKeyGen,
48 SortGen: SortableKeyGen,
49 SC: SymKeyComposerWrapper,
50 StC: StaticKeyComposerWrapper,
51 SignC: SignComposerWrapper,
52 SearchC: SearchableKeyComposerWrapper,
53 SortC: SortableKeyComposerWrapper,
54 PC: PkFromUserKeyWrapper,
55 VC: VerifyKFromUserKeyWrapper,
56 PwH: PwHash,
57{
58 user_id: UserId,
59 user_identifier: String,
60 device_id: DeviceId,
61
62 jwt: String,
63 refresh_token: String,
64
65 mfa: bool,
66
67 private_device_key: StC::SkWrapper,
69 public_device_key: StC::PkWrapper,
70 sign_device_key: SignC::SignKWrapper,
71 verify_device_key: SignC::VerifyKWrapper,
72 exported_verify_device_key: UserVerifyKeyData,
73 exported_public_device_key: UserPublicKeyData,
74
75 #[allow(clippy::type_complexity)]
77 user_keys: Vec<UserKeyDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>>,
78 key_map: KeyMap,
79 newest_key_id: SymKeyId,
80 hmac_keys: Vec<SearchC::SearchableKeyWrapper>,
81
82 base_url: String,
83 app_token: String,
84
85 _sgen: PhantomData<SGen>,
86 _st_gen: PhantomData<StGen>,
87 _sign_gen: PhantomData<SignGen>,
88 _search_gen: PhantomData<SearchGen>,
89 _sort_gen: PhantomData<SortGen>,
90 _sc: PhantomData<SC>,
91 _st_c: PhantomData<StC>,
92 _sign_c: PhantomData<SignC>,
93 _search_c: PhantomData<SearchC>,
94 _sort_c: PhantomData<SortC>,
95 _pc: PhantomData<PC>,
96 _vc: PhantomData<VC>,
97 _pw: PhantomData<PwH>,
98}
99
100impl<SGen, StGen, SignGen, SearchGen, SortGen, SC, StC, SignC, SearchC, SortC, PC, VC, PwH>
101 User<SGen, StGen, SignGen, SearchGen, SortGen, SC, StC, SignC, SearchC, SortC, PC, VC, PwH>
102where
103 SGen: SymKeyGenWrapper,
104 StGen: StaticKeyPairWrapper,
105 SignGen: SignKeyPairWrapper,
106 SearchGen: SearchableKeyGen,
107 SortGen: SortableKeyGen,
108 SC: SymKeyComposerWrapper,
109 StC: StaticKeyComposerWrapper,
110 SignC: SignComposerWrapper,
111 SearchC: SearchableKeyComposerWrapper,
112 SortC: SortableKeyComposerWrapper,
113 PC: PkFromUserKeyWrapper,
114 VC: VerifyKFromUserKeyWrapper,
115 PwH: PwHash,
116{
117 #[allow(clippy::type_complexity)]
118 fn new_user(
119 base_url: String,
120 app_token: String,
121 user_identifier: String,
122 data: UserDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>,
123 mfa: bool,
124 ) -> Result<(Self, Vec<GroupHmacData>), SentcError>
125 {
126 let newest_key_id = data
127 .user_keys
128 .first()
129 .ok_or(SentcError::KeyNotFound)?
130 .group_key
131 .get_id()
132 .to_string();
133
134 let mut key_map: KeyMap = Default::default();
135
136 for (i, key) in data.user_keys.iter().enumerate() {
137 key_map.insert(key.group_key.get_id().to_string(), i);
138 }
139
140 Ok((
141 Self {
142 user_id: data.user_id,
143 user_identifier,
144 device_id: data.device_id,
145 jwt: data.jwt,
146 refresh_token: data.refresh_token,
147 mfa,
148 private_device_key: data.device_keys.private_key,
149 public_device_key: data.device_keys.public_key,
150 sign_device_key: data.device_keys.sign_key,
151 verify_device_key: data.device_keys.verify_key,
152 exported_verify_device_key: data.device_keys.exported_verify_key,
153 exported_public_device_key: data.device_keys.exported_public_key,
154 user_keys: data.user_keys,
155 key_map,
156 newest_key_id,
157 hmac_keys: Vec::with_capacity(data.hmac_keys.len()),
158 base_url,
159 app_token,
160
161 _sgen: Default::default(),
162 _st_gen: Default::default(),
163 _sign_gen: Default::default(),
164 _search_gen: Default::default(),
165 _sort_gen: Default::default(),
166 _sc: Default::default(),
167 _st_c: Default::default(),
168 _sign_c: Default::default(),
169 _search_c: Default::default(),
170 _sort_c: Default::default(),
171 _pc: Default::default(),
172 _vc: Default::default(),
173 _pw: Default::default(),
174 },
175 data.hmac_keys,
176 ))
177 }
178
179 #[cfg(not(feature = "network"))]
180 #[allow(clippy::too_many_arguments, clippy::type_complexity)]
181 pub fn new(
182 base_url: String,
183 app_token: String,
184 user_identifier: String,
185 data: UserDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>,
186 mfa: bool,
187 ) -> Result<Self, SentcError>
188 {
189 let (mut u, hmac_keys) = Self::new_user(base_url, app_token, user_identifier, data, mfa)?;
190
191 u.decrypt_hmac_keys_sync(hmac_keys)?;
192
193 Ok(u)
194 }
195
196 pub fn get_user_id(&self) -> &str
197 {
198 &self.user_id
199 }
200
201 pub fn get_identifier(&self) -> &str
202 {
203 &self.user_identifier
204 }
205
206 pub fn get_device_id(&self) -> &str
207 {
208 &self.device_id
209 }
210
211 pub fn get_jwt_sync(&self) -> &str
212 {
213 &self.jwt
214 }
215
216 pub fn get_refresh_token(&self) -> &str
217 {
218 &self.refresh_token
219 }
220
221 #[allow(clippy::type_complexity)]
222 pub fn get_newest_key(
223 &self,
224 ) -> Option<&UserKeyDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>>
225 {
226 let index = self.key_map.get(&self.newest_key_id).unwrap_or(&0);
227
228 self.user_keys.get(*index)
229 }
230
231 pub fn get_newest_public_key(&self) -> Option<&StC::PkWrapper>
232 {
233 self.get_newest_key().map(|k| &k.public_key)
234 }
235
236 pub fn get_newest_exported_public_key(&self) -> Option<&UserPublicKeyData>
237 {
238 self.get_newest_key().map(|k| &k.exported_public_key)
239 }
240
241 pub fn get_newest_sign_key(&self) -> Option<&SignC::SignKWrapper>
242 {
243 self.get_newest_key().map(|k| &k.sign_key)
244 }
245
246 pub fn set_jwt(&mut self, jwt: String)
247 {
248 self.jwt = jwt;
249 }
250
251 pub fn set_refresh_token(&mut self, refresh_token: String)
252 {
253 self.refresh_token = refresh_token;
254 }
255
256 #[allow(clippy::type_complexity)]
257 pub fn get_user_keys(
258 &self,
259 key_id: &str,
260 ) -> Option<&UserKeyDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>>
261 {
262 self.key_map
263 .get(key_id)
264 .and_then(|k| self.user_keys.get(*k))
265 }
266
267 pub fn has_user_keys(&self, key_id: &str) -> Option<&usize>
268 {
269 self.key_map.get(key_id)
270 }
271
272 pub fn prepare_register_device_keys(&self, sever_output: &str) -> Result<(String, UserPublicKeyData), SentcError>
273 {
274 let (keys, _) = self.prepare_group_keys_ref(0);
275
276 let key_session = self.user_keys.len() > 50;
277
278 Ok(SdkUser::<
279 SGen,
280 StGen,
281 SignGen,
282 SearchGen,
283 SortGen,
284 SC,
285 StC,
286 SignC,
287 SearchC,
288 SortC,
289 PC,
290 VC,
291 PwH,
292 >::prepare_register_device(sever_output, &keys, key_session)?)
293 }
294
295 pub fn get_mfa(&self) -> bool
296 {
297 self.mfa
298 }
299
300 pub(crate) fn prepare_group_keys_ref(&self, page: usize) -> (Vec<&SC::SymmetricKeyWrapper>, bool)
301 {
302 prepare_group_keys_ref!(self.user_keys, page, 50)
303 }
304
305 pub fn get_private_device_key(&self) -> &StC::SkWrapper
306 {
307 &self.private_device_key
308 }
309
310 pub fn get_public_device_key(&self) -> &StC::PkWrapper
311 {
312 &self.public_device_key
313 }
314
315 pub fn get_verify_device_key(&self) -> &SignC::VerifyKWrapper
316 {
317 &self.verify_device_key
318 }
319
320 pub fn get_exported_verify_device_key(&self) -> &UserVerifyKeyData
321 {
322 &self.exported_verify_device_key
323 }
324
325 pub fn get_exported_public_device_key(&self) -> &UserPublicKeyData
326 {
327 &self.exported_public_device_key
328 }
329
330 #[cfg(not(feature = "network"))]
331 fn decrypt_hmac_keys_sync(&mut self, hmac_keys: Vec<GroupHmacData>) -> Result<(), SentcError>
332 {
333 for hmac_key in hmac_keys {
334 let key = self
335 .get_user_keys(&hmac_key.encrypted_hmac_encryption_key_id)
336 .ok_or(SentcError::KeyNotFound)?;
337
338 let decrypted_hmac_key =
339 SdkGroup::<SGen, StGen, SignGen, SearchGen, SortGen, SC, StC, SignC, SearchC, SortC, PC, VC>::decrypt_group_hmac_key(
340 &key.group_key,
341 hmac_key,
342 )?;
343
344 self.hmac_keys.push(decrypted_hmac_key);
345 }
346
347 Ok(())
348 }
349
350 #[allow(clippy::type_complexity)]
351 pub fn set_hmac_key(
352 &mut self,
353 user_key: &UserKeyDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>,
354 hmac_key: GroupHmacData,
355 ) -> Result<(), SentcError>
356 {
357 let decrypted_hmac_key =
358 SdkGroup::<SGen, StGen, SignGen, SearchGen, SortGen, SC, StC, SignC, SearchC, SortC, PC, VC>::decrypt_group_hmac_key(
359 &user_key.group_key,
360 hmac_key,
361 )?;
362
363 self.hmac_keys.push(decrypted_hmac_key);
364
365 Ok(())
366 }
367
368 pub fn prepare_create_group(&self, sign: bool) -> Result<String, SentcError>
369 {
370 let sign_key = if sign { self.get_newest_sign_key() } else { None };
371
372 Ok(SdkGroup::<
373 SGen,
374 StGen,
375 SignGen,
376 SearchGen,
377 SortGen,
378 SC,
379 StC,
380 SignC,
381 SearchC,
382 SortC,
383 PC,
384 VC,
385 >::prepare_create(
386 self.get_newest_public_key()
387 .ok_or(SentcError::KeyNotFound)?,
388 sign_key,
389 self.user_id.to_string(),
390 )?)
391 }
392
393 pub fn create_safety_number_sync(&self, other_user: Option<&str>, other_user_key: Option<&UserVerifyKeyData>) -> Result<String, SentcError>
394 {
395 Ok(SdkUser::<
396 SGen,
397 StGen,
398 SignGen,
399 SearchGen,
400 SortGen,
401 SC,
402 StC,
403 SignC,
404 SearchC,
405 SortC,
406 PC,
407 VC,
408 PwH,
409 >::create_safety_number(
410 &self
411 .get_newest_key()
412 .ok_or(SentcError::KeyNotFound)?
413 .exported_verify_key,
414 self.get_user_id(),
415 other_user_key,
416 other_user,
417 )?)
418 }
419
420 pub fn set_newest_key_id(&mut self, id: SymKeyId)
421 {
422 self.newest_key_id = id;
423 }
424
425 #[allow(clippy::type_complexity)]
426 pub fn extend_user_key(
427 &mut self,
428 user_keys: UserKeyDataInt<SC::SymmetricKeyWrapper, StC::SkWrapper, StC::PkWrapper, SignC::SignKWrapper, SignC::VerifyKWrapper>,
429 )
430 {
431 self.key_map
433 .insert(user_keys.group_key.get_id().to_string(), self.user_keys.len());
434 self.user_keys.push(user_keys);
435 }
436
437 pub fn prepare_register(user_identifier: &str, password: &str) -> Result<String, SentcError>
440 {
441 if user_identifier.is_empty() || password.is_empty() {
442 return Err(SentcError::UsernameOrPasswordRequired);
443 }
444
445 Ok(SdkUser::<
446 SGen,
447 StGen,
448 SignGen,
449 SearchGen,
450 SortGen,
451 SC,
452 StC,
453 SignC,
454 SearchC,
455 SortC,
456 PC,
457 VC,
458 PwH,
459 >::register(user_identifier, password)?)
460 }
461
462 pub fn prepare_register_device_start(device_identifier: &str, password: &str) -> Result<String, SentcError>
463 {
464 if device_identifier.is_empty() || password.is_empty() {
465 return Err(SentcError::UsernameOrPasswordRequired);
466 }
467
468 Ok(SdkUser::<
469 SGen,
470 StGen,
471 SignGen,
472 SearchGen,
473 SortGen,
474 SC,
475 StC,
476 SignC,
477 SearchC,
478 SortC,
479 PC,
480 VC,
481 PwH,
482 >::prepare_register_device_start(device_identifier, password)?)
483 }
484}
485
486pub fn generate_register_data() -> Result<(String, String), SentcError>
487{
488 Ok(generate_user_register_data()?)
489}
490
491pub fn done_register(server_output: &str) -> Result<UserId, SentcError>
492{
493 Ok(sentc_crypto::user::done_register(server_output)?)
494}
495
496pub fn done_register_device_start(server_output: &str) -> Result<(), SentcError>
497{
498 Ok(sentc_crypto::user::done_register_device_start(server_output)?)
499}