bitwarden_core/auth/
register.rs1use bitwarden_api_identity::{
2 apis::accounts_api::accounts_register_post,
3 models::{KeysRequestModel, RegisterRequestModel},
4};
5use bitwarden_crypto::{
6 default_pbkdf2_iterations, CryptoError, HashPurpose, Kdf, MasterKey, RsaKeyPair,
7};
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10
11use crate::{ApiError, Client};
12
13#[derive(Serialize, Deserialize, Debug)]
14#[serde(rename_all = "camelCase", deny_unknown_fields)]
15pub struct RegisterRequest {
16 pub email: String,
17 pub name: Option<String>,
18 pub password: String,
19 pub password_hint: Option<String>,
20}
21
22#[derive(Debug, Error)]
23pub enum RegisterError {
24 #[error(transparent)]
25 Crypto(#[from] CryptoError),
26 #[error(transparent)]
27 Api(#[from] ApiError),
28}
29
30pub(super) async fn register(client: &Client, req: &RegisterRequest) -> Result<(), RegisterError> {
32 let config = client.internal.get_api_configurations().await;
33
34 let kdf = Kdf::default();
35
36 let keys = make_register_keys(req.email.to_owned(), req.password.to_owned(), kdf)?;
37
38 accounts_register_post(
39 &config.identity,
40 Some(RegisterRequestModel {
41 name: req.name.to_owned(),
42 email: req.email.to_owned(),
43 master_password_hash: keys.master_password_hash,
44 master_password_hint: req.password_hint.to_owned(),
45 captcha_response: None, key: Some(keys.encrypted_user_key.to_string()),
47 keys: Some(Box::new(KeysRequestModel {
48 public_key: keys.keys.public,
49 encrypted_private_key: keys.keys.private.to_string(),
50 })),
51 token: None,
52 organization_user_id: None,
53 kdf: Some(bitwarden_api_identity::models::KdfType::PBKDF2_SHA256),
54 kdf_iterations: Some(default_pbkdf2_iterations().get() as i32),
55 kdf_memory: None,
56 kdf_parallelism: None,
57 reference_data: None, }),
59 )
60 .await
61 .map_err(ApiError::from)?;
62
63 Ok(())
64}
65
66pub(super) fn make_register_keys(
67 email: String,
68 password: String,
69 kdf: Kdf,
70) -> Result<RegisterKeyResponse, CryptoError> {
71 let master_key = MasterKey::derive(&password, &email, &kdf)?;
72 let master_password_hash =
73 master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization)?;
74 let (user_key, encrypted_user_key) = master_key.make_user_key()?;
75 let keys = user_key.make_key_pair()?;
76
77 Ok(RegisterKeyResponse {
78 master_password_hash,
79 encrypted_user_key: encrypted_user_key.to_string(),
80 keys,
81 })
82}
83
84#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
85pub struct RegisterKeyResponse {
86 pub master_password_hash: String,
87 pub encrypted_user_key: String,
88 pub keys: RsaKeyPair,
89}