Skip to content

Commit 0e948af

Browse files
dani-garciarenovate[bot]Hinton
authored
Unify WASM crypto client with mobile (#226)
## 🎟️ Tracking <!-- Paste the link to the Jira or GitHub issue or otherwise describe / point to where this change is coming from. --> ## 📔 Objective With the removal of the lifetimes of the clients, we can remove the wasm-specific crypto client and instead use the one in bitwarden-core. ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Oscar Hinton <[email protected]>
1 parent 4f00e70 commit 0e948af

File tree

15 files changed

+77
-113
lines changed

15 files changed

+77
-113
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bitwarden-core/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ uniffi = ["bitwarden-crypto/uniffi", "dep:uniffi"] # Uniffi bindings
2424
wasm = [
2525
"bitwarden-error/wasm",
2626
"dep:wasm-bindgen",
27+
"dep:wasm-bindgen-futures",
2728
"dep:tsify-next"
2829
] # WASM support
2930

@@ -50,6 +51,7 @@ tsify-next = { workspace = true, optional = true }
5051
uniffi = { workspace = true, optional = true, features = ["tokio"] }
5152
uuid = { workspace = true }
5253
wasm-bindgen = { workspace = true, optional = true }
54+
wasm-bindgen-futures = { workspace = true, optional = true }
5355
zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] }
5456
zxcvbn = { version = ">=3.0.1, <4.0", optional = true }
5557

crates/bitwarden-core/src/auth/auth_request.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ mod tests {
140140
use bitwarden_crypto::{Kdf, MasterKey};
141141

142142
use super::*;
143-
use crate::{
144-
key_management::SymmetricKeyId,
145-
mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest},
143+
use crate::key_management::{
144+
crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest},
145+
SymmetricKeyId,
146146
};
147147

148148
#[test]

crates/bitwarden-core/src/auth/login/auth_request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
auth_request::new_auth_request,
1313
},
1414
client::{LoginMethod, UserLoginMethod},
15-
mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest},
15+
key_management::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest},
1616
require, ApiError, Client,
1717
};
1818

crates/bitwarden-core/src/client/test_accounts.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ use std::collections::HashMap;
44
use bitwarden_crypto::{EncString, Kdf};
55

66
use crate::{
7-
mobile::crypto::{
8-
initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoMethod,
9-
InitUserCryptoRequest,
10-
},
7+
key_management::crypto::{InitOrgCryptoRequest, InitUserCryptoMethod, InitUserCryptoRequest},
118
Client,
129
};
1310

@@ -20,10 +17,14 @@ impl Client {
2017
true,
2118
)]));
2219

23-
initialize_user_crypto(&client, account.user).await.unwrap();
20+
client
21+
.crypto()
22+
.initialize_user_crypto(account.user)
23+
.await
24+
.unwrap();
2425

2526
if let Some(org) = account.org {
26-
initialize_org_crypto(&client, org).await.unwrap();
27+
client.crypto().initialize_org_crypto(org).await.unwrap();
2728
}
2829

2930
client

crates/bitwarden-core/src/mobile/crypto.rs renamed to crates/bitwarden-core/src/key_management/crypto.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use bitwarden_crypto::{
1111
AsymmetricCryptoKey, CryptoError, EncString, Kdf, KeyDecryptable, KeyEncryptable, MasterKey,
1212
SymmetricCryptoKey, UnsignedSharedKey, UserKey,
1313
};
14+
use bitwarden_error::bitwarden_error;
15+
use schemars::JsonSchema;
1416
use serde::{Deserialize, Serialize};
1517
#[cfg(feature = "wasm")]
1618
use {tsify_next::Tsify, wasm_bindgen::prelude::*};
@@ -23,8 +25,9 @@ use crate::{
2325

2426
/// Catch all error for mobile crypto operations.
2527
#[allow(missing_docs)]
28+
#[bitwarden_error(flat)]
2629
#[derive(Debug, thiserror::Error)]
27-
pub enum MobileCryptoError {
30+
pub enum CryptoClientError {
2831
#[error(transparent)]
2932
NotAuthenticated(#[from] NotAuthenticatedError),
3033
#[error(transparent)]
@@ -123,7 +126,7 @@ pub enum AuthRequestMethod {
123126
}
124127

125128
/// Initialize the user's cryptographic state.
126-
pub async fn initialize_user_crypto(
129+
pub(super) async fn initialize_user_crypto(
127130
client: &Client,
128131
req: InitUserCryptoRequest,
129132
) -> Result<(), EncryptionSettingsError> {
@@ -236,7 +239,7 @@ pub struct InitOrgCryptoRequest {
236239
}
237240

238241
/// Initialize the user's organizational cryptographic state.
239-
pub(crate) async fn initialize_org_crypto(
242+
pub(super) async fn initialize_org_crypto(
240243
client: &Client,
241244
req: InitOrgCryptoRequest,
242245
) -> Result<(), EncryptionSettingsError> {
@@ -245,7 +248,7 @@ pub(crate) async fn initialize_org_crypto(
245248
Ok(())
246249
}
247250

248-
pub(super) async fn get_user_encryption_key(client: &Client) -> Result<String, MobileCryptoError> {
251+
pub(super) async fn get_user_encryption_key(client: &Client) -> Result<String, CryptoClientError> {
249252
let key_store = client.internal.get_key_store();
250253
let ctx = key_store.context();
251254
// This is needed because the mobile clients need access to the user encryption key
@@ -259,6 +262,7 @@ pub(super) async fn get_user_encryption_key(client: &Client) -> Result<String, M
259262
#[derive(Serialize, Deserialize, Debug)]
260263
#[serde(rename_all = "camelCase", deny_unknown_fields)]
261264
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
265+
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
262266
pub struct UpdatePasswordResponse {
263267
/// Hash of the new password
264268
password_hash: String,
@@ -269,7 +273,7 @@ pub struct UpdatePasswordResponse {
269273
pub(super) fn update_password(
270274
client: &Client,
271275
new_password: String,
272-
) -> Result<UpdatePasswordResponse, MobileCryptoError> {
276+
) -> Result<UpdatePasswordResponse, CryptoClientError> {
273277
let key_store = client.internal.get_key_store();
274278
let ctx = key_store.context();
275279
// FIXME: [PM-18099] Once MasterKey deals with KeyIds, this should be updated
@@ -308,6 +312,7 @@ pub(super) fn update_password(
308312
#[derive(Serialize, Deserialize, Debug)]
309313
#[serde(rename_all = "camelCase", deny_unknown_fields)]
310314
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
315+
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
311316
pub struct DerivePinKeyResponse {
312317
/// [UserKey] protected by PIN
313318
pin_protected_user_key: EncString,
@@ -318,7 +323,7 @@ pub struct DerivePinKeyResponse {
318323
pub(super) fn derive_pin_key(
319324
client: &Client,
320325
pin: String,
321-
) -> Result<DerivePinKeyResponse, MobileCryptoError> {
326+
) -> Result<DerivePinKeyResponse, CryptoClientError> {
322327
let key_store = client.internal.get_key_store();
323328
let ctx = key_store.context();
324329
// FIXME: [PM-18099] Once PinKey deals with KeyIds, this should be updated
@@ -341,7 +346,7 @@ pub(super) fn derive_pin_key(
341346
pub(super) fn derive_pin_user_key(
342347
client: &Client,
343348
encrypted_pin: EncString,
344-
) -> Result<EncString, MobileCryptoError> {
349+
) -> Result<EncString, CryptoClientError> {
345350
let key_store = client.internal.get_key_store();
346351
let ctx = key_store.context();
347352
// FIXME: [PM-18099] Once PinKey deals with KeyIds, this should be updated
@@ -361,7 +366,7 @@ fn derive_pin_protected_user_key(
361366
pin: &str,
362367
login_method: &LoginMethod,
363368
user_key: &SymmetricCryptoKey,
364-
) -> Result<EncString, MobileCryptoError> {
369+
) -> Result<EncString, CryptoClientError> {
365370
use bitwarden_crypto::PinKey;
366371

367372
let derived_key = match login_method {
@@ -377,6 +382,7 @@ fn derive_pin_protected_user_key(
377382
}
378383

379384
#[allow(missing_docs)]
385+
#[bitwarden_error(flat)]
380386
#[derive(Debug, thiserror::Error)]
381387
pub enum EnrollAdminPasswordResetError {
382388
#[error(transparent)]
@@ -408,7 +414,10 @@ pub(super) fn enroll_admin_password_reset(
408414
}
409415

410416
/// Request for migrating an account from password to key connector.
417+
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
418+
#[serde(rename_all = "camelCase", deny_unknown_fields)]
411419
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
420+
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
412421
pub struct DeriveKeyConnectorRequest {
413422
/// Encrypted user key, used to validate the master key
414423
pub user_key_encrypted: EncString,
@@ -421,6 +430,7 @@ pub struct DeriveKeyConnectorRequest {
421430
}
422431

423432
#[allow(missing_docs)]
433+
#[bitwarden_error(flat)]
424434
#[derive(Debug, thiserror::Error)]
425435
pub enum DeriveKeyConnectorError {
426436
#[error(transparent)]

crates/bitwarden-core/src/mobile/crypto_client.rs renamed to crates/bitwarden-core/src/key_management/crypto_client.rs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
use bitwarden_crypto::CryptoError;
22
#[cfg(feature = "internal")]
33
use bitwarden_crypto::{EncString, UnsignedSharedKey};
4+
#[cfg(feature = "wasm")]
5+
use wasm_bindgen::prelude::*;
46

57
use super::crypto::{
6-
derive_key_connector, make_key_pair, verify_asymmetric_keys, DeriveKeyConnectorError,
7-
DeriveKeyConnectorRequest, EnrollAdminPasswordResetError, MakeKeyPairResponse,
8-
MobileCryptoError, VerifyAsymmetricKeysRequest, VerifyAsymmetricKeysResponse,
8+
derive_key_connector, make_key_pair, verify_asymmetric_keys, CryptoClientError,
9+
DeriveKeyConnectorError, DeriveKeyConnectorRequest, EnrollAdminPasswordResetError,
10+
MakeKeyPairResponse, VerifyAsymmetricKeysRequest, VerifyAsymmetricKeysResponse,
911
};
1012
#[cfg(feature = "internal")]
11-
use crate::mobile::crypto::{
13+
use crate::key_management::crypto::{
1214
derive_pin_key, derive_pin_user_key, enroll_admin_password_reset, get_user_encryption_key,
1315
initialize_org_crypto, initialize_user_crypto, update_password, DerivePinKeyResponse,
1416
InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse,
1517
};
1618
use crate::{client::encryption_settings::EncryptionSettingsError, Client};
1719

1820
/// A client for the crypto operations.
21+
#[cfg_attr(feature = "wasm", wasm_bindgen)]
1922
pub struct CryptoClient {
2023
pub(crate) client: crate::Client,
2124
}
2225

26+
#[cfg_attr(feature = "wasm", wasm_bindgen)]
2327
impl CryptoClient {
2428
/// Initialization method for the user crypto. Needs to be called before any other crypto
2529
/// operations.
@@ -39,9 +43,27 @@ impl CryptoClient {
3943
initialize_org_crypto(&self.client, req).await
4044
}
4145

46+
/// Generates a new key pair and encrypts the private key with the provided user key.
47+
/// Crypto initialization not required.
48+
pub fn make_key_pair(&self, user_key: String) -> Result<MakeKeyPairResponse, CryptoError> {
49+
make_key_pair(user_key)
50+
}
51+
52+
/// Verifies a user's asymmetric keys by decrypting the private key with the provided user
53+
/// key. Returns if the private key is decryptable and if it is a valid matching key.
54+
/// Crypto initialization not required.
55+
pub fn verify_asymmetric_keys(
56+
&self,
57+
request: VerifyAsymmetricKeysRequest,
58+
) -> Result<VerifyAsymmetricKeysResponse, CryptoError> {
59+
verify_asymmetric_keys(request)
60+
}
61+
}
62+
63+
impl CryptoClient {
4264
/// Get the uses's decrypted encryption key. Note: It's very important
4365
/// to keep this key safe, as it can be used to decrypt all of the user's data
44-
pub async fn get_user_encryption_key(&self) -> Result<String, MobileCryptoError> {
66+
pub async fn get_user_encryption_key(&self) -> Result<String, CryptoClientError> {
4567
get_user_encryption_key(&self.client).await
4668
}
4769

@@ -50,14 +72,14 @@ impl CryptoClient {
5072
pub fn update_password(
5173
&self,
5274
new_password: String,
53-
) -> Result<UpdatePasswordResponse, MobileCryptoError> {
75+
) -> Result<UpdatePasswordResponse, CryptoClientError> {
5476
update_password(&self.client, new_password)
5577
}
5678

5779
/// Generates a PIN protected user key from the provided PIN. The result can be stored and later
5880
/// used to initialize another client instance by using the PIN and the PIN key with
5981
/// `initialize_user_crypto`.
60-
pub fn derive_pin_key(&self, pin: String) -> Result<DerivePinKeyResponse, MobileCryptoError> {
82+
pub fn derive_pin_key(&self, pin: String) -> Result<DerivePinKeyResponse, CryptoClientError> {
6183
derive_pin_key(&self.client, pin)
6284
}
6385

@@ -66,7 +88,7 @@ impl CryptoClient {
6688
pub fn derive_pin_user_key(
6789
&self,
6890
encrypted_pin: EncString,
69-
) -> Result<EncString, MobileCryptoError> {
91+
) -> Result<EncString, CryptoClientError> {
7092
derive_pin_user_key(&self.client, encrypted_pin)
7193
}
7294

@@ -86,21 +108,6 @@ impl CryptoClient {
86108
) -> Result<String, DeriveKeyConnectorError> {
87109
derive_key_connector(request)
88110
}
89-
90-
/// Generates a new key pair and encrypts the private key with the provided user key.
91-
pub fn make_key_pair(&self, user_key: String) -> Result<MakeKeyPairResponse, CryptoError> {
92-
make_key_pair(user_key)
93-
}
94-
95-
/// Verifies a user's asymmetric keys by decrypting the private key with the provided user
96-
/// key. Returns if the private key is decryptable and if it is a valid matching key.
97-
/// Crypto initialization not required.
98-
pub fn verify_asymmetric_keys(
99-
&self,
100-
request: VerifyAsymmetricKeysRequest,
101-
) -> Result<VerifyAsymmetricKeysResponse, CryptoError> {
102-
verify_asymmetric_keys(request)
103-
}
104111
}
105112

106113
impl Client {

crates/bitwarden-core/src/key_management/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
//! [Encryptable](bitwarden_crypto::Encryptable) and [Decryptable](bitwarden_crypto::Encryptable).
1010
use bitwarden_crypto::{key_ids, KeyStore, SymmetricCryptoKey};
1111

12+
pub mod crypto;
13+
mod crypto_client;
14+
15+
pub use crypto_client::CryptoClient;
16+
1217
key_ids! {
1318
#[symmetric]
1419
pub enum SymmetricKeyId {

crates/bitwarden-core/src/mobile/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
//! This module consists of stop-gap functionality for the mobile clients until the SDK owns it's
44
//! own state.
55
6-
pub mod crypto;
76
mod kdf;
87

98
mod client_kdf;
10-
mod crypto_client;
119

1210
pub use client_kdf::KdfClient;
13-
pub use crypto_client::CryptoClient;

crates/bitwarden-core/tests/register.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ async fn test_register_initialize_crypto() {
77
use std::num::NonZeroU32;
88

99
use bitwarden_core::{
10-
mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest},
10+
key_management::crypto::{InitUserCryptoMethod, InitUserCryptoRequest},
1111
Client,
1212
};
1313
use bitwarden_crypto::Kdf;

0 commit comments

Comments
 (0)