Skip to content
Open
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
44773f7
Adds MasterPasswordUnlock into identity's response user decryption opโ€ฆ
mzieniukbw Aug 4, 2025
0712878
Adds MasterPasswordUnlock KDF change handling in sync
mzieniukbw Aug 4, 2025
8ca20a8
simplification
mzieniukbw Aug 5, 2025
28a8423
clippy fix
mzieniukbw Aug 5, 2025
b089ea0
formatting
mzieniukbw Aug 5, 2025
0d35393
no handling, just response parsing
mzieniukbw Aug 5, 2025
a08179d
test coverage
mzieniukbw Aug 5, 2025
b3647f2
wasm
mzieniukbw Aug 5, 2025
36d3136
wasm unit test coverage
mzieniukbw Aug 5, 2025
7c8664d
wasm unit test coverage
mzieniukbw Aug 5, 2025
9c7d50d
Added UserDecryption data, response model with handling
mzieniukbw Aug 5, 2025
70ad9d3
autogenerated wasm responses, UserDecryption struct, use of TryFrom
mzieniukbw Aug 7, 2025
110f4db
failing unit test
mzieniukbw Aug 7, 2025
ff86adf
lint
mzieniukbw Aug 7, 2025
fa253a3
lint
mzieniukbw Aug 7, 2025
4a95dc5
KdfType enum duplicate
mzieniukbw Aug 7, 2025
cd37e31
revert identity crate wasm, since there it's not used right now
mzieniukbw Aug 8, 2025
3bf880f
docs
mzieniukbw Aug 8, 2025
93a3d0c
formatting
mzieniukbw Aug 8, 2025
fa1b16b
Add update SDK functionality
quexten Aug 13, 2025
af83c57
Add test
quexten Aug 13, 2025
e780d69
Cleanup
quexten Aug 13, 2025
f0c4f2a
Merge branch 'main' into km/pm-24051-add-master-password-unlock-decryโ€ฆ
mzieniukbw Aug 13, 2025
3e6a46a
revert user decryption response parsing in wasm
mzieniukbw Aug 13, 2025
7c34725
fixed unit test
mzieniukbw Aug 13, 2025
042678c
revert wasm dependencies
mzieniukbw Aug 13, 2025
9676069
bring back wasm and uniffi bindings to MasterPasswordUnlockData, erroโ€ฆ
mzieniukbw Aug 13, 2025
bcc183a
Fix clippy issues
quexten Aug 14, 2025
6398e13
Fix build
quexten Aug 14, 2025
e816975
Merge branch 'km/pm-24051-add-master-password-unlock-decryption-optioโ€ฆ
quexten Aug 14, 2025
21c72e0
Fix build
quexten Aug 14, 2025
3dc3577
Clean-up errors
quexten Aug 14, 2025
367f9f0
Fix formatting
quexten Aug 14, 2025
3d9b257
Replace String with str
quexten Aug 14, 2025
69ed59c
Fix wasm being imported on UNIFFI builds
quexten Aug 14, 2025
866912b
Feature-flag wasm-only code and fix import
quexten Aug 14, 2025
08d10fe
Merge branch 'fix-wasm-import' into km/update-kdf-sdk
quexten Aug 14, 2025
0aba54b
Fix clippy issues
quexten Aug 14, 2025
4e41a29
Fix clippy issue
quexten Aug 14, 2025
7973f12
identity separate user decryption options response model
mzieniukbw Aug 15, 2025
5a4f314
review suggestions
mzieniukbw Aug 15, 2025
7e425ca
identity name prefix for UserDecryptionOptions
mzieniukbw Aug 15, 2025
c9aaa8c
IdentityUserDecryptionOptionsResponseModel mapping to UserDecryptionData
mzieniukbw Aug 15, 2025
2591773
clippy
mzieniukbw Aug 15, 2025
c908173
Merge branch 'km/pm-24051-add-master-password-unlock-decryption-optioโ€ฆ
quexten Aug 15, 2025
9f2c473
Expose update kdf in uniffi
quexten Aug 15, 2025
ed3be99
Merge branch 'km/update-kdf-sdk' of github.com:bitwarden/sdk-internalโ€ฆ
quexten Aug 15, 2025
48bfbda
Update crates/bitwarden-core/src/key_management/crypto.rs
quexten Aug 19, 2025
b4d89e2
Update crates/bitwarden-core/src/key_management/crypto.rs
quexten Aug 19, 2025
aeaeff5
Rename to make_update
quexten Aug 19, 2025
7cf85b4
Merge branch 'km/update-kdf-sdk' of github.com:bitwarden/sdk-internalโ€ฆ
quexten Aug 19, 2025
3212002
Merge branch 'main' into km/pm-24051-add-master-password-unlock-decryโ€ฆ
mzieniukbw Aug 19, 2025
1a3dd14
Update comments
quexten Aug 19, 2025
55cc2b7
Rename error variant
quexten Aug 19, 2025
dd5dd3e
Rename error variant
quexten Aug 19, 2025
20b5a06
Fix build
quexten Aug 19, 2025
18e7913
Merge branch 'km/pm-24051-add-master-password-unlock-decryption-optioโ€ฆ
quexten Aug 19, 2025
5cf50d2
Undo duplicate upstream change
quexten Aug 19, 2025
6cdb29b
Fix formatting
quexten Aug 19, 2025
77c2d68
missing kdf fields treated as missing field error
mzieniukbw Aug 19, 2025
a487fff
Merge branch 'main' into km/pm-24051-add-master-password-unlock-decryโ€ฆ
mzieniukbw Aug 19, 2025
ecfde52
Merge branch 'main' into km/pm-24051-add-master-password-unlock-decryโ€ฆ
mzieniukbw Aug 20, 2025
8d5c8c4
Undo duplicate import
quexten Aug 22, 2025
d5a7180
Update crates/bitwarden-core/src/key_management/crypto_client.rs
quexten Aug 22, 2025
285132a
Remove long-path import
quexten Aug 22, 2025
aec1105
Mark as deprecated
quexten Aug 22, 2025
16f73ce
Remove unused function
quexten Aug 22, 2025
47da2c9
Merge branch 'km/update-kdf-sdk' of github.com:bitwarden/sdk-internalโ€ฆ
quexten Aug 22, 2025
0b99b78
Merge branch 'km/pm-24051-add-master-password-unlock-decryption-optioโ€ฆ
quexten Aug 22, 2025
77a142e
Fix clippy errors
quexten Aug 22, 2025
c703c10
Undo deprecation changes
quexten Aug 22, 2025
db8e8b0
Merge branch 'km/update-kdf-sdk' of github.com:bitwarden/sdk-internalโ€ฆ
quexten Aug 22, 2025
139d2b1
Merge branch 'main' into km/update-kdf-sdk
quexten Sep 3, 2025
a0ede96
Resolve conflicts
quexten Sep 3, 2025
198c29c
Merge branch 'main' into km/update-kdf-sdk
quexten Sep 4, 2025
06f160a
Remove identity_user_decryption_options_response
jlf0dev Sep 10, 2025
35c0e8d
address PR feedback
jlf0dev Sep 10, 2025
07b25ed
Merge branch 'main' into km/update-kdf-sdk
jlf0dev Sep 10, 2025
f2dff60
use to_owned instead of clone
jlf0dev Sep 10, 2025
b0030e4
reword unlock to authenticate
jlf0dev Sep 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use bitwarden_api_identity::models::KdfType;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::auth::api::response::identity_user_decryption_options_response::IdentityUserDecryptionOptionsResponseModel;

#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct IdentityTokenSuccessResponse {
pub access_token: String,
Expand Down Expand Up @@ -35,6 +37,9 @@ pub struct IdentityTokenSuccessResponse {
#[serde(rename = "keyConnectorUrl", alias = "KeyConnectorUrl")]
key_connector_url: Option<String>,

#[serde(rename = "userDecryptionOptions", alias = "UserDecryptionOptions")]
pub user_decryption_options: Option<IdentityUserDecryptionOptionsResponseModel>,

/// Stores unknown api response fields
extra: Option<HashMap<String, Value>>,
}
Expand All @@ -61,6 +66,7 @@ mod test {
force_password_reset: Default::default(),
api_use_key_connector: Default::default(),
key_connector_url: Default::default(),
user_decryption_options: Default::default(),
extra: Default::default(),
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use bitwarden_api_api::models::MasterPasswordUnlockResponseModel;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct IdentityUserDecryptionOptionsResponseModel {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Why not use #[serde(rename_all = "camelCase")] rather than renaming the field?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This response model was actually leftover from a previous upstream PR. Removed since its not needed.

#[serde(
rename = "masterPasswordUnlock",
skip_serializing_if = "Option::is_none"
)]
pub master_password_unlock: Option<MasterPasswordUnlockResponseModel>,
}
1 change: 1 addition & 0 deletions crates/bitwarden-core/src/auth/api/response/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod identity_success_response;
mod identity_token_fail_response;
mod identity_token_response;
mod identity_two_factor_response;
pub(crate) mod identity_user_decryption_options_response;
pub(crate) mod two_factor_provider_data;
mod two_factor_providers;

Expand Down
2 changes: 1 addition & 1 deletion crates/bitwarden-core/src/auth/login/password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub(crate) async fn login_password(

let master_key = MasterKey::derive(&input.password, &input.email, &input.kdf)?;
let password_hash = master_key
.derive_master_key_hash(input.password.as_bytes(), HashPurpose::ServerAuthorization)?;
.derive_master_key_hash(input.password.as_bytes(), HashPurpose::ServerAuthorization);

let response = request_identity_tokens(client, input, &password_hash).await?;

Expand Down
2 changes: 1 addition & 1 deletion crates/bitwarden-core/src/auth/password/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) fn determine_password_hash(
purpose: HashPurpose,
) -> Result<String, CryptoError> {
let master_key = MasterKey::derive(password, email, kdf)?;
master_key.derive_master_key_hash(password.as_bytes(), purpose)
Ok(master_key.derive_master_key_hash(password.as_bytes(), purpose))
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion crates/bitwarden-core/src/auth/password/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub(crate) fn validate_password_user_key(
}

Ok(master_key
.derive_master_key_hash(password.as_bytes(), HashPurpose::LocalAuthorization)?)
.derive_master_key_hash(password.as_bytes(), HashPurpose::LocalAuthorization))
}
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion crates/bitwarden-core/src/auth/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub(super) fn make_register_keys(
) -> Result<RegisterKeyResponse, CryptoError> {
let master_key = MasterKey::derive(&password, &email, &kdf)?;
let master_password_hash =
master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization)?;
master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization);
let (user_key, encrypted_user_key) = master_key.make_user_key()?;
let keys = user_key.make_key_pair()?;

Expand Down
161 changes: 158 additions & 3 deletions crates/bitwarden-core/src/key_management/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
client::{encryption_settings::EncryptionSettingsError, LoginMethod, UserLoginMethod},
error::StatefulCryptoError,
key_management::{
master_password::{MasterPasswordAuthenticationData, MasterPasswordUnlockData},
AsymmetricKeyId, SecurityState, SignedSecurityState, SigningKeyId, SymmetricKeyId,
},
Client, NotAuthenticatedError, VaultLockedError, WrongPasswordError,
Expand All @@ -39,6 +40,8 @@ pub enum CryptoClientError {
VaultLocked(#[from] VaultLockedError),
#[error(transparent)]
Crypto(#[from] bitwarden_crypto::CryptoError),
#[error("Invalid KDF settings")]
InvalidKdfSettings,
}

/// State used for initializing the user cryptographic state.
Expand Down Expand Up @@ -265,6 +268,64 @@ pub(super) async fn get_user_encryption_key(client: &Client) -> Result<String, C
Ok(user_key.to_base64())
}

/// Response from the `update_kdf` function
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
pub struct UpdateKdfResponse {
/// The authentication data for the new KDF setting
master_password_authentication_data: MasterPasswordAuthenticationData,
/// The unlock data for the new KDF setting
master_password_unlock_data: MasterPasswordUnlockData,
/// The authentication data for the KDF setting prior to the change
old_master_password_authentication_data: MasterPasswordAuthenticationData,
}

pub(super) fn make_update_kdf(
client: &Client,
password: &str,
new_kdf: &Kdf,
) -> Result<UpdateKdfResponse, CryptoClientError> {
let key_store = client.internal.get_key_store();
let ctx = key_store.context();
// FIXME: [PM-18099] Once MasterKey deals with KeyIds, this should be updated
#[allow(deprecated)]
let user_key = ctx.dangerous_get_symmetric_key(SymmetricKeyId::User)?;

let login_method = client
.internal
.get_login_method()
.ok_or(NotAuthenticatedError)?;
let email = match login_method.as_ref() {
LoginMethod::User(
UserLoginMethod::Username { email, .. } | UserLoginMethod::ApiKey { email, .. },
) => email,
#[cfg(feature = "secrets")]
LoginMethod::ServiceAccount(_) => return Err(NotAuthenticatedError)?,
};

let authentication_data = MasterPasswordAuthenticationData::derive(password, new_kdf, email)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These derive functions will only fail if the KDF settings are insufficient right? If that's the case we should rename the error variant to make it more clear, because the error is unrelated to the master password.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. The variant is now just "InvalidKdfSettings", and discards the returned MasterPasswordError

.map_err(|_| CryptoClientError::InvalidKdfSettings)?;
let unlock_data = MasterPasswordUnlockData::derive(password, new_kdf, email, user_key)
.map_err(|_| CryptoClientError::InvalidKdfSettings)?;
let old_authentication_data = MasterPasswordAuthenticationData::derive(
password,
&client
.internal
.get_kdf()
.map_err(|_| NotAuthenticatedError)?,
email,
)
.map_err(|_| CryptoClientError::InvalidKdfSettings)?;

Ok(UpdateKdfResponse {
master_password_authentication_data: authentication_data,
master_password_unlock_data: unlock_data,
old_master_password_authentication_data: old_authentication_data,
})
}

/// Response from the `update_password` function
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
Expand All @@ -277,7 +338,7 @@ pub struct UpdatePasswordResponse {
new_key: EncString,
}

pub(super) fn update_password(
pub(super) fn make_update_password(
client: &Client,
new_password: String,
) -> Result<UpdatePasswordResponse, CryptoClientError> {
Expand Down Expand Up @@ -307,7 +368,7 @@ pub(super) fn update_password(
let password_hash = new_master_key.derive_master_key_hash(
new_password.as_bytes(),
bitwarden_crypto::HashPurpose::ServerAuthorization,
)?;
);

Ok(UpdatePasswordResponse {
password_hash,
Expand Down Expand Up @@ -737,6 +798,100 @@ mod tests {
"pgEBAlAmkP0QgfdMVbIujX55W/yNAycEgQIgBiFYIEM6JxBmjWQTruAm3s6BTaJy1q6BzQetMBacNeRJ0kxR";
const TEST_VECTOR_SECURITY_STATE_V2: &str = "hFgepAEnAxg8BFAmkP0QgfdMVbIujX55W/yNOgABOH8CoFgkomhlbnRpdHlJZFBHOOw2BI9OQoNq+Vl1xZZKZ3ZlcnNpb24CWEAlchbJR0vmRfShG8On7Q2gknjkw4Dd6MYBLiH4u+/CmfQdmjNZdf6kozgW/6NXyKVNu8dAsKsin+xxXkDyVZoG";

#[tokio::test]
async fn test_update_kdf() {
let client = Client::new(None);

let priv_key: EncString = "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw=".parse().unwrap();

let kdf = Kdf::PBKDF2 {
iterations: 100_000.try_into().unwrap(),
};

initialize_user_crypto(
& client,
InitUserCryptoRequest {
user_id: Some(uuid::Uuid::new_v4()),
kdf_params: kdf.clone(),
email: "[email protected]".into(),
private_key: priv_key.to_owned(),
signing_key: None,
security_state: None,
method: InitUserCryptoMethod::Password {
password: "asdfasdfasdf".into(),
user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(),
},
},
)
.await
.unwrap();

let new_kdf = Kdf::PBKDF2 {
iterations: 600_000.try_into().unwrap(),
};
let new_kdf_response = make_update_kdf(&client, "123412341234", &new_kdf).unwrap();

let client2 = Client::new(None);

initialize_user_crypto(
&client2,
InitUserCryptoRequest {
user_id: Some(uuid::Uuid::new_v4()),
kdf_params: new_kdf.clone(),
email: "[email protected]".into(),
private_key: priv_key.to_owned(),
signing_key: None,
security_state: None,
method: InitUserCryptoMethod::Password {
password: "123412341234".into(),
user_key: new_kdf_response
.master_password_unlock_data
.master_key_wrapped_user_key,
},
},
)
.await
.unwrap();

let new_hash = client2
.kdf()
.hash_password(
"[email protected]".into(),
"123412341234".into(),
new_kdf.clone(),
bitwarden_crypto::HashPurpose::ServerAuthorization,
)
.await
.unwrap();

assert_eq!(
new_hash,
new_kdf_response
.master_password_authentication_data
.master_password_authentication_hash
);

let client_key = {
let key_store = client.internal.get_key_store();
let ctx = key_store.context();
#[allow(deprecated)]
ctx.dangerous_get_symmetric_key(SymmetricKeyId::User)
.unwrap()
.to_base64()
};

let client2_key = {
let key_store = client2.internal.get_key_store();
let ctx = key_store.context();
#[allow(deprecated)]
ctx.dangerous_get_symmetric_key(SymmetricKeyId::User)
.unwrap()
.to_base64()
};

assert_eq!(client_key, client2_key);
}

#[tokio::test]
async fn test_update_password() {
let client = Client::new(None);
Expand Down Expand Up @@ -765,7 +920,7 @@ mod tests {
.await
.unwrap();

let new_password_response = update_password(&client, "123412341234".into()).unwrap();
let new_password_response = make_update_password(&client, "123412341234".into()).unwrap();

let client2 = Client::new(None);

Expand Down
38 changes: 31 additions & 7 deletions crates/bitwarden-core/src/key_management/crypto_client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bitwarden_crypto::CryptoError;
use bitwarden_crypto::{CryptoError, Kdf};
#[cfg(feature = "internal")]
use bitwarden_crypto::{EncString, UnsignedSharedKey};
#[cfg(feature = "wasm")]
Expand All @@ -12,15 +12,15 @@ use super::crypto::{
#[cfg(feature = "internal")]
use crate::key_management::crypto::{
derive_pin_key, derive_pin_user_key, enroll_admin_password_reset, get_user_encryption_key,
initialize_org_crypto, initialize_user_crypto, update_password, DerivePinKeyResponse,
initialize_org_crypto, initialize_user_crypto, make_update_password, DerivePinKeyResponse,
InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse,
};
use crate::{
client::encryption_settings::EncryptionSettingsError,
error::StatefulCryptoError,
key_management::crypto::{
get_v2_rotated_account_keys, make_v2_keys_for_v1_user, CryptoClientError,
UserCryptoV2KeysResponse,
get_v2_rotated_account_keys, make_update_kdf, make_v2_keys_for_v1_user, CryptoClientError,
UpdateKdfResponse, UserCryptoV2KeysResponse,
},
Client,
};
Expand Down Expand Up @@ -80,6 +80,17 @@ impl CryptoClient {
) -> Result<UserCryptoV2KeysResponse, StatefulCryptoError> {
get_v2_rotated_account_keys(&self.client)
}

/// Create the data necessary to update the user's kdf settings. The user's encryption key is
/// re-encrypted for the password under the new kdf settings. This returns the new encrypted
/// user key and the new password hash but does not update sdk state.
pub fn make_update_kdf(
&self,
password: String,
kdf: Kdf,
) -> Result<UpdateKdfResponse, CryptoClientError> {
make_update_kdf(&self.client, &password, &kdf)
}
}

impl CryptoClient {
Expand All @@ -89,13 +100,26 @@ impl CryptoClient {
get_user_encryption_key(&self.client).await
}

/// Update the user's password, which will re-encrypt the user's encryption key with the new
/// password. This returns the new encrypted user key and the new password hash.
/// Create the data necessary to update the user's password. The user's encryption key is
/// re-encrypted with the new password. This returns the new encrypted user key and the new
/// password hash but does not update sdk state.
///
/// Note: This is deprecated and `make_update_password` should be used instead
pub fn update_password(
&self,
new_password: String,
) -> Result<UpdatePasswordResponse, CryptoClientError> {
update_password(&self.client, new_password)
self.make_update_password(new_password)
}

/// Create the data necessary to update the user's password. The user's encryption key is
/// re-encrypted with the new password. This returns the new encrypted user key and the new
/// password hash but does not update sdk state.
pub fn make_update_password(
&self,
new_password: String,
) -> Result<UpdatePasswordResponse, CryptoClientError> {
make_update_password(&self.client, new_password)
}

/// Generates a PIN protected user key from the provided PIN. The result can be stored and later
Expand Down
Loading