From 8b0cc6d02d8da8d24cf787e61740cb693c7c2824 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 14:51:04 +0200 Subject: [PATCH 1/7] Add support for initializing crypto using key connector and generating master key for key connector --- crates/bitwarden-core/src/auth/client_auth.rs | 8 ++++ .../bitwarden-core/src/auth/key_connector.rs | 41 +++++++++++++++++++ crates/bitwarden-core/src/auth/mod.rs | 2 + crates/bitwarden-core/src/mobile/crypto.rs | 41 ++++++++++--------- .../bitwarden-crypto/src/keys/master_key.rs | 18 +++++++- 5 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 crates/bitwarden-core/src/auth/key_connector.rs diff --git a/crates/bitwarden-core/src/auth/client_auth.rs b/crates/bitwarden-core/src/auth/client_auth.rs index 6f1afb135..2e210bd87 100644 --- a/crates/bitwarden-core/src/auth/client_auth.rs +++ b/crates/bitwarden-core/src/auth/client_auth.rs @@ -1,3 +1,4 @@ +use bitwarden_crypto::CryptoError; #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmetricEncString, DeviceKey, EncString, Kdf, TrustDeviceResponse}; @@ -23,6 +24,8 @@ use crate::auth::{ }; use crate::{auth::renew::renew_token, error::Result, Client}; +use super::key_connector::{make_key_connector_keys, KeyConnectorResponse}; + pub struct ClientAuth<'a> { pub(crate) client: &'a crate::Client, } @@ -79,6 +82,11 @@ impl<'a> ClientAuth<'a> { make_register_tde_keys(self.client, email, org_public_key, remember_device) } + pub fn make_key_connector_keys(&self) -> Result { + let mut rng = rand::thread_rng(); + make_key_connector_keys(&mut rng) + } + pub async fn register(&self, input: &RegisterRequest) -> Result<()> { register(self.client, input).await } diff --git a/crates/bitwarden-core/src/auth/key_connector.rs b/crates/bitwarden-core/src/auth/key_connector.rs new file mode 100644 index 000000000..0ff3da35c --- /dev/null +++ b/crates/bitwarden-core/src/auth/key_connector.rs @@ -0,0 +1,41 @@ +use bitwarden_crypto::{CryptoError, MasterKey, RsaKeyPair}; + +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +pub struct KeyConnectorResponse { + pub master_key: String, + pub encrypted_user_key: String, + pub keys: RsaKeyPair, +} + +pub(super) fn make_key_connector_keys( + mut rng: impl rand::RngCore, +) -> Result { + let master_key = MasterKey::generate(&mut rng); + let (user_key, encrypted_user_key) = master_key.make_user_key()?; + let keys = user_key.make_key_pair()?; + + Ok(KeyConnectorResponse { + master_key: master_key.to_base64(), + encrypted_user_key: encrypted_user_key.to_string(), + keys, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use rand::SeedableRng; + use rand_chacha::ChaCha8Rng; + + #[test] + fn test_make_key_connector_keys() { + let mut rng = ChaCha8Rng::from_seed([0u8; 32]); + + let result = make_key_connector_keys(&mut rng).unwrap(); + + assert_eq!( + result.master_key, + "PgDvL4lfQNZ/W7joHwmloSyEDsPOmn87GBvhiO9xGh4=" + ); + } +} diff --git a/crates/bitwarden-core/src/auth/mod.rs b/crates/bitwarden-core/src/auth/mod.rs index e52870570..6fe22bb57 100644 --- a/crates/bitwarden-core/src/auth/mod.rs +++ b/crates/bitwarden-core/src/auth/mod.rs @@ -30,6 +30,8 @@ pub use register::{RegisterKeyResponse, RegisterRequest}; mod tde; #[cfg(feature = "internal")] pub use tde::RegisterTdeKeyResponse; +#[cfg(feature = "internal")] +mod key_connector; #[cfg(feature = "internal")] use crate::error::Result; diff --git a/crates/bitwarden-core/src/mobile/crypto.rs b/crates/bitwarden-core/src/mobile/crypto.rs index 3f8bc562c..12e2d92af 100644 --- a/crates/bitwarden-core/src/mobile/crypto.rs +++ b/crates/bitwarden-core/src/mobile/crypto.rs @@ -1,19 +1,18 @@ use std::collections::HashMap; -use bitwarden_crypto::{AsymmetricEncString, EncString}; -#[cfg(feature = "internal")] -use bitwarden_crypto::{Kdf, KeyDecryptable, KeyEncryptable, MasterKey, SymmetricCryptoKey}; +use bitwarden_crypto::{ + AsymmetricEncString, EncString, Kdf, KeyDecryptable, KeyEncryptable, MasterKey, + SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[cfg(feature = "internal")] -use crate::client::{LoginMethod, UserLoginMethod}; use crate::{ + client::{LoginMethod, UserLoginMethod}, error::{Error, Result}, Client, }; -#[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] @@ -28,7 +27,6 @@ pub struct InitUserCryptoRequest { pub method: InitUserCryptoMethod, } -#[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] @@ -64,9 +62,14 @@ pub enum InitUserCryptoMethod { /// The user's symmetric crypto key, encrypted with the Device Key. device_protected_user_key: AsymmetricEncString, }, + KeyConnector { + /// Base64 encoded master key, retrieved from the key connector. + master_key: String, + /// The user's encrypted symmetric crypto key + user_key: String, + }, } -#[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] @@ -83,7 +86,6 @@ pub enum AuthRequestMethod { }, } -#[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &Client, req: InitUserCryptoRequest) -> Result<()> { use bitwarden_crypto::{DeviceKey, PinKey}; @@ -151,6 +153,17 @@ pub async fn initialize_user_crypto(client: &Client, req: InitUserCryptoRequest) .internal .initialize_user_crypto_decrypted_key(user_key, private_key)?; } + InitUserCryptoMethod::KeyConnector { + master_key, + user_key, + } => { + let master_key = MasterKey::new(SymmetricCryptoKey::try_from(master_key)?); + let user_key: EncString = user_key.parse()?; + + client + .internal + .initialize_user_crypto_master_key(master_key, user_key, private_key)?; + } } client @@ -166,7 +179,6 @@ pub async fn initialize_user_crypto(client: &Client, req: InitUserCryptoRequest) Ok(()) } -#[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] @@ -175,14 +187,12 @@ pub struct InitOrgCryptoRequest { pub organization_keys: HashMap, } -#[cfg(feature = "internal")] pub async fn initialize_org_crypto(client: &Client, req: InitOrgCryptoRequest) -> Result<()> { let organization_keys = req.organization_keys.into_iter().collect(); client.internal.initialize_org_crypto(organization_keys)?; Ok(()) } -#[cfg(feature = "internal")] pub async fn get_user_encryption_key(client: &Client) -> Result { let enc = client.internal.get_encryption_settings()?; let user_key = enc.get_key(&None)?; @@ -190,7 +200,6 @@ pub async fn get_user_encryption_key(client: &Client) -> Result { Ok(user_key.to_base64()) } -#[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] @@ -233,7 +242,6 @@ pub fn update_password(client: &Client, new_password: String) -> Result Result { let enc = client.internal.get_encryption_settings()?; let user_key = enc.get_key(&None)?; @@ -262,7 +269,6 @@ pub fn derive_pin_key(client: &Client, pin: String) -> Result Result { let enc = client.internal.get_encryption_settings()?; let user_key = enc.get_key(&None)?; @@ -276,7 +282,6 @@ pub fn derive_pin_user_key(client: &Client, encrypted_pin: EncString) -> Result< derive_pin_protected_user_key(&pin, &login_method, user_key) } -#[cfg(feature = "internal")] fn derive_pin_protected_user_key( pin: &str, login_method: &LoginMethod, @@ -296,7 +301,6 @@ fn derive_pin_protected_user_key( Ok(derived_key.encrypt_user_key(user_key)?) } -#[cfg(feature = "internal")] pub(super) fn enroll_admin_password_reset( client: &Client, public_key: String, @@ -495,7 +499,6 @@ mod tests { ); } - #[cfg(feature = "internal")] #[test] fn test_enroll_admin_password_reset() { use std::num::NonZeroU32; diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 83e51a1b2..fc9762c3c 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -1,6 +1,8 @@ use std::num::NonZeroU32; use base64::{engine::general_purpose::STANDARD, Engine}; +use generic_array::{typenum::U32, GenericArray}; +use rand::Rng; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -64,10 +66,20 @@ pub enum HashPurpose { pub struct MasterKey(SymmetricCryptoKey); impl MasterKey { - pub fn new(key: SymmetricCryptoKey) -> MasterKey { + pub fn new(key: SymmetricCryptoKey) -> Self { Self(key) } + /// Generate a new random master key. Primarily used for KeyConnector. + pub fn generate(mut rng: impl rand::RngCore) -> Self { + let mut key = Box::pin(GenericArray::::default()); + + rng.fill(key.as_mut_slice()); + + // Master Keys never contains a mac_key. + Self::new(SymmetricCryptoKey { key, mac_key: None }) + } + /// Derives a users master key from their password, email and KDF. /// /// Note: the email is trimmed and converted to lowercase before being used. @@ -101,6 +113,10 @@ impl MasterKey { pub fn decrypt_user_key(&self, user_key: EncString) -> Result { decrypt_user_key(&self.0, user_key) } + + pub fn to_base64(&self) -> String { + self.0.to_base64() + } } /// Helper function to encrypt a user key with a master or pin key. From 3f5cb9ec49a8d35ad0cbfc2a4ab2c2a1065f1853 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 14:51:48 +0200 Subject: [PATCH 2/7] fmt --- crates/bitwarden-core/src/auth/client_auth.rs | 3 +-- crates/bitwarden-core/src/auth/key_connector.rs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-core/src/auth/client_auth.rs b/crates/bitwarden-core/src/auth/client_auth.rs index 2e210bd87..1188cfd90 100644 --- a/crates/bitwarden-core/src/auth/client_auth.rs +++ b/crates/bitwarden-core/src/auth/client_auth.rs @@ -2,6 +2,7 @@ use bitwarden_crypto::CryptoError; #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmetricEncString, DeviceKey, EncString, Kdf, TrustDeviceResponse}; +use super::key_connector::{make_key_connector_keys, KeyConnectorResponse}; #[cfg(feature = "internal")] use crate::auth::login::NewAuthRequestResponse; #[cfg(feature = "secrets")] @@ -24,8 +25,6 @@ use crate::auth::{ }; use crate::{auth::renew::renew_token, error::Result, Client}; -use super::key_connector::{make_key_connector_keys, KeyConnectorResponse}; - pub struct ClientAuth<'a> { pub(crate) client: &'a crate::Client, } diff --git a/crates/bitwarden-core/src/auth/key_connector.rs b/crates/bitwarden-core/src/auth/key_connector.rs index 0ff3da35c..b4006b472 100644 --- a/crates/bitwarden-core/src/auth/key_connector.rs +++ b/crates/bitwarden-core/src/auth/key_connector.rs @@ -23,10 +23,11 @@ pub(super) fn make_key_connector_keys( #[cfg(test)] mod tests { - use super::*; use rand::SeedableRng; use rand_chacha::ChaCha8Rng; + use super::*; + #[test] fn test_make_key_connector_keys() { let mut rng = ChaCha8Rng::from_seed([0u8; 32]); From 52154b8fa7d1288a331c261e2d57020c59586ef7 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 14:56:32 +0200 Subject: [PATCH 3/7] Expose make_key_connector_keys to uniffi --- crates/bitwarden-core/src/auth/mod.rs | 2 ++ crates/bitwarden-uniffi/src/auth/mod.rs | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-core/src/auth/mod.rs b/crates/bitwarden-core/src/auth/mod.rs index 6fe22bb57..30babdc7d 100644 --- a/crates/bitwarden-core/src/auth/mod.rs +++ b/crates/bitwarden-core/src/auth/mod.rs @@ -32,6 +32,8 @@ mod tde; pub use tde::RegisterTdeKeyResponse; #[cfg(feature = "internal")] mod key_connector; +#[cfg(feature = "internal")] +pub use key_connector::KeyConnectorResponse; #[cfg(feature = "internal")] use crate::error::Result; diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 644580c5d..d036991e3 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -1,8 +1,11 @@ use std::sync::Arc; -use bitwarden::auth::{ - password::MasterPasswordPolicyOptions, AuthRequestResponse, RegisterKeyResponse, - RegisterTdeKeyResponse, +use bitwarden::{ + auth::{ + password::MasterPasswordPolicyOptions, AuthRequestResponse, KeyConnectorResponse, + RegisterKeyResponse, RegisterTdeKeyResponse, + }, + Error, }; use bitwarden_crypto::{AsymmetricEncString, EncString, HashPurpose, Kdf, TrustDeviceResponse}; @@ -79,6 +82,16 @@ impl ClientAuth { .make_register_tde_keys(email, org_public_key, remember_device)?) } + /// Generate keys needed to onboard a new user without master key to key connector + pub fn make_key_connector_keys(&self) -> Result { + Ok(self + .0 + .0 + .auth() + .make_key_connector_keys() + .map_err(Error::Crypto)?) + } + /// Validate the user password /// /// To retrieve the user's password hash, use [`ClientAuth::hash_password`] with From 64a0fbbb9a8e883b8801197b60a5c5ce391505c7 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 15:57:01 +0200 Subject: [PATCH 4/7] Expose a way to get the master key to send to key connector --- .../src/mobile/client_crypto.rs | 14 ++++++------- crates/bitwarden-core/src/mobile/crypto.rs | 20 +++++++++++++++++++ crates/bitwarden-uniffi/src/crypto.rs | 8 +++++++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/crates/bitwarden-core/src/mobile/client_crypto.rs b/crates/bitwarden-core/src/mobile/client_crypto.rs index 88e359844..ac07f21b6 100644 --- a/crates/bitwarden-core/src/mobile/client_crypto.rs +++ b/crates/bitwarden-core/src/mobile/client_crypto.rs @@ -12,45 +12,45 @@ use crate::{ }, }; +use super::crypto::{derive_key_connector, DeriveKeyConnectorRequest}; + pub struct ClientCrypto<'a> { pub(crate) client: &'a crate::Client, } impl<'a> ClientCrypto<'a> { - #[cfg(feature = "internal")] pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> { initialize_user_crypto(self.client, req).await } - #[cfg(feature = "internal")] pub async fn initialize_org_crypto(&self, req: InitOrgCryptoRequest) -> Result<()> { initialize_org_crypto(self.client, req).await } - #[cfg(feature = "internal")] pub async fn get_user_encryption_key(&self) -> Result { get_user_encryption_key(self.client).await } - #[cfg(feature = "internal")] pub fn update_password(&self, new_password: String) -> Result { update_password(self.client, new_password) } - #[cfg(feature = "internal")] pub fn derive_pin_key(&self, pin: String) -> Result { derive_pin_key(self.client, pin) } - #[cfg(feature = "internal")] pub fn derive_pin_user_key(&self, encrypted_pin: EncString) -> Result { derive_pin_user_key(self.client, encrypted_pin) } - #[cfg(feature = "internal")] pub fn enroll_admin_password_reset(&self, public_key: String) -> Result { enroll_admin_password_reset(self.client, public_key) } + + /// Derive the master key for migrating to the key connector + pub fn derive_key_connector(&self, request: DeriveKeyConnectorRequest) -> Result { + derive_key_connector(request) + } } impl<'a> Client { diff --git a/crates/bitwarden-core/src/mobile/crypto.rs b/crates/bitwarden-core/src/mobile/crypto.rs index 12e2d92af..04502388d 100644 --- a/crates/bitwarden-core/src/mobile/crypto.rs +++ b/crates/bitwarden-core/src/mobile/crypto.rs @@ -318,6 +318,26 @@ pub(super) fn enroll_admin_password_reset( )?) } +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +pub struct DeriveKeyConnectorRequest { + /// Encrypted user key, used to validate the master key + pub user_key_encrypted: EncString, + + pub password: String, + pub kdf: Kdf, + pub email: String, +} + +/// Derive the master key for migrating to the key connector +pub(super) fn derive_key_connector(request: DeriveKeyConnectorRequest) -> Result { + let master_key = MasterKey::derive(&request.password, &request.email, &request.kdf)?; + master_key + .decrypt_user_key(request.user_key_encrypted) + .map_err(|_| "wrong password")?; + + Ok(master_key.to_base64()) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 761a72bc2..8a089404a 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -1,7 +1,8 @@ use std::sync::Arc; use bitwarden::mobile::crypto::{ - DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse, + DeriveKeyConnectorRequest, DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, + UpdatePasswordResponse, }; use bitwarden_crypto::{AsymmetricEncString, EncString}; @@ -52,4 +53,9 @@ impl ClientCrypto { pub fn enroll_admin_password_reset(&self, public_key: String) -> Result { Ok(self.0 .0.crypto().enroll_admin_password_reset(public_key)?) } + + /// Derive the master key for migrating to the key connector + pub fn derive_key_connector(&self, request: DeriveKeyConnectorRequest) -> Result { + Ok(self.0 .0.crypto().derive_key_connector(request)?) + } } From be2650a87d41efdb35f51b6088fcd84c4b2653a6 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 16:29:39 +0200 Subject: [PATCH 5/7] Fix linting --- crates/bitwarden-core/src/auth/client_auth.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bitwarden-core/src/auth/client_auth.rs b/crates/bitwarden-core/src/auth/client_auth.rs index 1188cfd90..829868556 100644 --- a/crates/bitwarden-core/src/auth/client_auth.rs +++ b/crates/bitwarden-core/src/auth/client_auth.rs @@ -1,18 +1,18 @@ -use bitwarden_crypto::CryptoError; #[cfg(feature = "internal")] -use bitwarden_crypto::{AsymmetricEncString, DeviceKey, EncString, Kdf, TrustDeviceResponse}; +use bitwarden_crypto::{ + AsymmetricEncString, CryptoError, DeviceKey, EncString, Kdf, TrustDeviceResponse, +}; -use super::key_connector::{make_key_connector_keys, KeyConnectorResponse}; -#[cfg(feature = "internal")] -use crate::auth::login::NewAuthRequestResponse; #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::auth::{ auth_request::{approve_auth_request, new_auth_request}, + key_connector::{make_key_connector_keys, KeyConnectorResponse}, login::{ login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, - ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, + ApiKeyLoginResponse, NewAuthRequestResponse, PasswordLoginRequest, PasswordLoginResponse, + TwoFactorEmailRequest, }, password::{ password_strength, satisfies_policy, validate_password, validate_password_user_key, From b0161a04b056bdcfe6697a6a2b9f32578c6bf19e Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 16:46:28 +0200 Subject: [PATCH 6/7] Add test --- crates/bitwarden-core/src/mobile/crypto.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-core/src/mobile/crypto.rs b/crates/bitwarden-core/src/mobile/crypto.rs index 04502388d..15ddeb9b7 100644 --- a/crates/bitwarden-core/src/mobile/crypto.rs +++ b/crates/bitwarden-core/src/mobile/crypto.rs @@ -340,6 +340,8 @@ pub(super) fn derive_key_connector(request: DeriveKeyConnectorRequest) -> Result #[cfg(test)] mod tests { + use std::num::NonZeroU32; + use super::*; use crate::Client; @@ -521,8 +523,6 @@ mod tests { #[test] fn test_enroll_admin_password_reset() { - use std::num::NonZeroU32; - use base64::{engine::general_purpose::STANDARD, Engine}; use bitwarden_crypto::AsymmetricCryptoKey; @@ -557,4 +557,20 @@ mod tests { let expected = enc.get_key(&None).unwrap(); assert_eq!(&decrypted, &expected.to_vec()); } + + #[test] + fn test_derive_key_connector() { + let request = DeriveKeyConnectorRequest { + password: "asdfasdfasdf".to_string(), + email: "test@bitwarden.com".to_string(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + user_key_encrypted: "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(), + }; + + let result = derive_key_connector(request).unwrap(); + + assert_eq!(result, "ySXq1RVLKEaV1eoQE/ui9aFKIvXTl9PAXwp1MljfF50="); + } } From a8743955926546afa9f09a32ebbdbfeaa6c9f90e Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 15 Aug 2024 16:57:08 +0200 Subject: [PATCH 7/7] Format --- crates/bitwarden-core/src/mobile/client_crypto.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bitwarden-core/src/mobile/client_crypto.rs b/crates/bitwarden-core/src/mobile/client_crypto.rs index ac07f21b6..293b8f9b3 100644 --- a/crates/bitwarden-core/src/mobile/client_crypto.rs +++ b/crates/bitwarden-core/src/mobile/client_crypto.rs @@ -1,6 +1,7 @@ #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmetricEncString, EncString}; +use super::crypto::{derive_key_connector, DeriveKeyConnectorRequest}; use crate::Client; #[cfg(feature = "internal")] use crate::{ @@ -12,8 +13,6 @@ use crate::{ }, }; -use super::crypto::{derive_key_connector, DeriveKeyConnectorRequest}; - pub struct ClientCrypto<'a> { pub(crate) client: &'a crate::Client, }