Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
7fa725f
Implement security context
quexten Jul 3, 2025
0387b44
Cargo fmt
quexten Jul 3, 2025
6c1a57d
Apply clippy fixes
quexten Jul 3, 2025
f4bd1e2
Apply cargo fmt
quexten Jul 3, 2025
ae4590e
Fix build
quexten Jul 3, 2025
c7dc40a
Cleanup
quexten Jul 4, 2025
eaf788e
Update crates/bitwarden-core/src/key_management/crypto.rs
quexten Jul 4, 2025
c7854b4
Merge branch 'km/account-security-version' of github.com:bitwarden/sdโ€ฆ
quexten Jul 4, 2025
2c65c3d
Split init to two functions
quexten Jul 4, 2025
db94fd3
Replace `EncryptionSettingsError::Crypto` with into
quexten Jul 4, 2025
77a2ebe
Fix imports
quexten Jul 4, 2025
14f5d3f
Cargo fmt
quexten Jul 4, 2025
4fea3dc
Cleanup
quexten Jul 4, 2025
46d2202
Cleanup init with enum
quexten Jul 4, 2025
b20e5a4
Cleanup
quexten Jul 4, 2025
566dc47
Fix clippy warnings
quexten Jul 4, 2025
678a9e3
Move security state to core
quexten Jul 4, 2025
b891ec4
Fix version range
quexten Jul 4, 2025
3dd6366
Fix clippy errors
quexten Jul 4, 2025
24ec20d
Fix comment
quexten Jul 4, 2025
6f17cd4
Move serde bytes to workspace
quexten Jul 8, 2025
9922265
Make signing key and security state non-optional
quexten Jul 8, 2025
5f98cab
Remove unused import
quexten Jul 8, 2025
429066a
Add comment
quexten Jul 8, 2025
162e218
Remove unused import
quexten Jul 8, 2025
35677ac
Merge branch 'main' into km/account-security-version
quexten Jul 9, 2025
381b547
Tmp
quexten Jul 9, 2025
d89a17d
Simplify rotation usage, and store security state
quexten Jul 9, 2025
80fe0b7
Fix build
quexten Jul 10, 2025
3885e36
Fix sm build
quexten Jul 10, 2025
e6816f2
Apply clippy fixes
quexten Jul 10, 2025
96548c2
Apply clippy fixes
quexten Jul 10, 2025
620d3c2
Fix test
quexten Jul 10, 2025
959b2e7
Fix tests
quexten Jul 10, 2025
bf269f6
Remove unused import
quexten Jul 10, 2025
5902ea2
Rename to "UserCryptoV2KeysResponse"
quexten Jul 10, 2025
cd8077c
Update crates/bitwarden-core/src/key_management/mod.rs
quexten Jul 11, 2025
e063963
Fix renames
quexten Jul 11, 2025
a0ee4d7
Add error for base64 deserialization
quexten Jul 11, 2025
d10af3d
Clean up key rotation
quexten Jul 11, 2025
5d6ae55
Cleanup
quexten Jul 11, 2025
16c6248
Cleanup get_v2_rotated_account_keys
quexten Jul 11, 2025
d7dea45
Remove arc
quexten Jul 11, 2025
8a00fff
Remove remaining arc references
quexten Jul 11, 2025
4f2b05a
Fix build
quexten Jul 11, 2025
080c6ea
Merge branch 'main' into km/account-security-version
quexten Jul 11, 2025
f76daa8
Re-sort impl after definition
quexten Jul 11, 2025
9e44be8
Update comment
quexten Jul 11, 2025
2c64b9c
Remove json schema
quexten Jul 11, 2025
6e85d6b
Merge branch 'km/account-security-version' of github.com:bitwarden/sdโ€ฆ
quexten Jul 11, 2025
35821d9
Clarify comment
quexten Jul 11, 2025
d01b953
Add test for v1 user trying to rotate using v2 rotation method
quexten Jul 11, 2025
e3dea12
Cargo fmt
quexten Jul 14, 2025
da0a0d8
Extract individual user crypto state values into UserKeyState struct
quexten Jul 14, 2025
4bc1214
Fix build
quexten Jul 14, 2025
7c4f562
Swap to uuid
quexten Jul 14, 2025
ee78cb7
Move impl to struct
quexten Jul 14, 2025
f4007c1
Clean up imports
quexten Jul 14, 2025
1e25d0e
Clean up imports
quexten Jul 14, 2025
17758a4
Fix build
quexten Jul 14, 2025
a85f84f
Add test vectors and tests
quexten Jul 14, 2025
932f9b8
Add comment for signature keys on registration
quexten Jul 14, 2025
2511017
Lift up use
quexten Jul 14, 2025
8ce7e26
Cargo fmt
quexten Jul 14, 2025
95827df
Move stateful crypto error to core crate
quexten Jul 14, 2025
6fa7eff
Fix build on non-internal feature flag
quexten Jul 14, 2025
dfaaca9
Filter import to internal feature only
quexten Jul 14, 2025
736f744
Merge branch 'main' into km/account-security-version
quexten Jul 14, 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
11 changes: 9 additions & 2 deletions crates/bitwarden-core/src/auth/auth_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ mod tests {
let private_key ="2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse().unwrap();
client
.internal
.initialize_user_crypto_master_key(master_key, user_key, private_key, None)
.initialize_user_crypto_master_key(master_key, user_key, private_key, None, None)
.unwrap();

let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyLRDUwXB4BfQ507D4meFPmwn5zwy3IqTPJO4plrrhnclWahXa240BzyFW9gHgYu+Jrgms5xBfRTBMcEsqqNm7+JpB6C1B6yvnik0DpJgWQw1rwvy4SUYidpR/AWbQi47n/hvnmzI/sQxGddVfvWu1iTKOlf5blbKYAXnUE5DZBGnrWfacNXwRRdtP06tFB0LwDgw+91CeLSJ9py6dm1qX5JIxoO8StJOQl65goLCdrTWlox+0Jh4xFUfCkb+s3px+OhSCzJbvG/hlrSRcUz5GnwlCEyF3v5lfUtV96MJD+78d8pmH6CfFAp2wxKRAbGdk+JccJYO6y6oIXd3Fm7twIDAQAB";
Expand Down Expand Up @@ -232,7 +232,13 @@ mod tests {

existing_device
.internal
.initialize_user_crypto_master_key(master_key, user_key, private_key.clone(), None)
.initialize_user_crypto_master_key(
master_key,
user_key,
private_key.clone(),
None,
None,
)
.unwrap();

// Initialize a new device which will request to be logged in
Expand All @@ -251,6 +257,7 @@ mod tests {
email: email.to_owned(),
private_key,
signing_key: None,
security_state: None,
method: InitUserCryptoMethod::AuthRequest {
request_private_key: auth_req.private_key,
method: AuthRequestMethod::UserKey {
Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-core/src/auth/login/api_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub(crate) async fn login_api_key(
user_key,
private_key,
None,
None,
)?;
}

Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-core/src/auth/login/auth_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub(crate) async fn complete_auth_request(
email: auth_req.email,
private_key: require!(r.private_key).parse()?,
signing_key: None,
security_state: None,
method: InitUserCryptoMethod::AuthRequest {
request_private_key: auth_req.private_key,
method,
Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-core/src/auth/login/password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub(crate) async fn login_password(
user_key,
private_key,
None,
None,
)?;
}

Expand Down
2 changes: 2 additions & 0 deletions crates/bitwarden-core/src/auth/password/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ mod tests {
user_key.parse().unwrap(),
private_key,
None,
None,
)
.unwrap();

Expand Down Expand Up @@ -193,6 +194,7 @@ mod tests {
user_key.parse().unwrap(),
private_key,
None,
None,
)
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-core/src/auth/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ mod tests {
user_key.parse().unwrap(),
private_key,
None,
None,
)
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-core/src/auth/tde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub(super) fn make_register_tde_keys(
// Note: Signing keys are not supported on registration yet. This needs to be changed as
// soon as registration is supported.
None,
None,
)?;

Ok(RegisterTdeKeyResponse {
Expand Down
114 changes: 77 additions & 37 deletions crates/bitwarden-core/src/client/encryption_settings.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[cfg(feature = "internal")]
use bitwarden_crypto::{EncString, UnsignedSharedKey};
use bitwarden_crypto::{security_state::SignedSecurityState, EncString, UnsignedSharedKey};
use bitwarden_crypto::{CryptoError, Pkcs8PrivateKeyBytes};
#[cfg(any(feature = "internal", feature = "secrets"))]
use bitwarden_crypto::{KeyStore, SymmetricCryptoKey};
use bitwarden_error::bitwarden_error;
Expand Down Expand Up @@ -30,6 +31,9 @@ pub enum EncryptionSettingsError {
#[error("Invalid signing key")]
InvalidSigningKey,

#[error("Invalid security state")]
InvalidSecurityState,

#[error(transparent)]
MissingPrivateKey(#[from] MissingPrivateKeyError),

Expand All @@ -50,49 +54,85 @@ impl EncryptionSettings {
user_key: SymmetricCryptoKey,
private_key: EncString,
signing_key: Option<EncString>,
security_state: Option<SignedSecurityState>,
Copy link
Member

Choose a reason for hiding this comment

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

Suggestion: If signing_key and security_state will both always be defined when using a chacha key, I wonder if it would simplify the logic if instead of having two optional values, we combined both parameters into a struct and made that optional instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've moved the entire set of keys into enum variants now. The type of symmetric key is also enforced by the type system.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note this required an allow(large_enum_variant). I feel that this is OK since we only have one instance of this enum in the sdk.

Copy link
Member

Choose a reason for hiding this comment

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

Looks good to me, yeah that warning can be safely ignored for this case, I think.

store: &KeyStore<KeyIds>,
) -> Result<(), EncryptionSettingsError> {
use bitwarden_crypto::{AsymmetricCryptoKey, CoseSerializable, KeyDecryptable, SigningKey};
use bitwarden_crypto::{AsymmetricCryptoKey, KeyDecryptable};
use log::warn;

use crate::key_management::{AsymmetricKeyId, SigningKeyId, SymmetricKeyId};

let private_key = {
let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
// FIXME: [PM-11690] - Temporarily ignore invalid private keys until we have a recovery
// process in place.
AsymmetricCryptoKey::from_der(&dec.into())
.map_err(|_| {
warn!("Invalid private key");
})
.ok()

// Some(
// AsymmetricCryptoKey::from_der(&dec)
// .map_err(|_| EncryptionSettingsError::InvalidPrivateKey)?,
// )
};
let signing_key = signing_key
.map(|key| {
use bitwarden_crypto::CryptoError;

let dec: Vec<u8> = key.decrypt_with_key(&user_key)?;
SigningKey::from_cose(&dec.into()).map_err(Into::<CryptoError>::into)
})
.transpose()?;

// FIXME: [PM-18098] When this is part of crypto we won't need to use deprecated methods
#[allow(deprecated)]
{
let mut ctx = store.context_mut();
ctx.set_symmetric_key(SymmetricKeyId::User, user_key)?;
if let Some(private_key) = private_key {
use crate::key_management::{AsymmetricKeyId, SymmetricKeyId};

// This is an all-or-nothing check. The server cannot pretend a signing key or security
// state to be missing, because they are *always* present when the user key is an
// XChaCha20Poly1305Key. Thus, the server or network cannot lie about the presence of these,
// because otherwise the entire user account will fail to decrypt.
let is_v2_user = matches!(user_key, SymmetricCryptoKey::XChaCha20Poly1305Key(_));
if is_v2_user {
// For v2 users, we mandate the signing key and security state to be present
// The private key must also be valid.

use bitwarden_crypto::{
security_state::SecurityState, CoseKeyBytes, CoseSerializable, SigningKey,
};

// Both of these are required for v2 users
let signing_key = signing_key.ok_or(EncryptionSettingsError::Crypto(
CryptoError::SecurityDowngrade("Signing key is required for v2 users".to_string()),
))?;
let security_state = security_state.ok_or(EncryptionSettingsError::Crypto(
CryptoError::SecurityDowngrade(
"Security state is required for v2 users".to_string(),
),
))?;

// Everything MUST decrypt.
let signing_key: Vec<u8> = signing_key.decrypt_with_key(&user_key)?;
let signing_key = SigningKey::from_cose(&CoseKeyBytes::from(signing_key))
.map_err(|_| EncryptionSettingsError::InvalidSigningKey)?;
let private_key: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
let private_key =
AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(private_key))
.map_err(|_| EncryptionSettingsError::InvalidPrivateKey)?;
let _security_state: SecurityState = security_state
.verify_and_unwrap(&signing_key.to_verifying_key())
.map_err(|_| EncryptionSettingsError::InvalidSecurityState)?;

#[allow(deprecated)]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Making the entire block as allow deprecated since each of the context functions requires this. This will be removed when we remove external access to these set functions.

Question for reviewers: Would it make sense to split these into a non-deprecated pub(crate) and to a deprecated pub fn dangerous_... similar to the get functions?

{
use crate::key_management::SigningKeyId;

let mut ctx = store.context_mut();
ctx.set_symmetric_key(SymmetricKeyId::User, user_key)?;
ctx.set_asymmetric_key(AsymmetricKeyId::UserPrivateKey, private_key)?;
}

if let Some(signing_key) = signing_key {
ctx.set_signing_key(SigningKeyId::UserSigningKey, signing_key)?;
}
} else {
let private_key = {
let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;

// FIXME: [PM-11690] - Temporarily ignore invalid private keys until we have a
// recovery process in place.
AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(dec))
.map_err(|_| {
warn!("Invalid private key");
})
.ok()

// Some(
// AsymmetricCryptoKey::from_der(&dec)
// .map_err(|_| EncryptionSettingsError::InvalidPrivateKey)?,
// )
};

// FIXME: [PM-18098] When this is part of crypto we won't need to use deprecated methods
#[allow(deprecated)]
{
let mut ctx = store.context_mut();
ctx.set_symmetric_key(SymmetricKeyId::User, user_key)?;
if let Some(private_key) = private_key {
ctx.set_asymmetric_key(AsymmetricKeyId::UserPrivateKey, private_key)?;
}
}
}

Ok(())
Expand Down
30 changes: 26 additions & 4 deletions crates/bitwarden-core/src/client/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use bitwarden_crypto::KeyStore;
#[cfg(any(feature = "internal", feature = "secrets"))]
use bitwarden_crypto::SymmetricCryptoKey;
#[cfg(feature = "internal")]
use bitwarden_crypto::{EncString, Kdf, MasterKey, PinKey, UnsignedSharedKey};
use bitwarden_crypto::{
security_state::SignedSecurityState, EncString, Kdf, MasterKey, PinKey, UnsignedSharedKey,
};
#[cfg(feature = "internal")]
use bitwarden_state::registry::StateRegistry;
use chrono::Utc;
Expand Down Expand Up @@ -217,9 +219,16 @@ impl InternalClient {
user_key: EncString,
private_key: EncString,
signing_key: Option<EncString>,
security_state: Option<SignedSecurityState>,
) -> Result<(), EncryptionSettingsError> {
let user_key = master_key.decrypt_user_key(user_key)?;
EncryptionSettings::new_decrypted_key(user_key, private_key, signing_key, &self.key_store)?;
EncryptionSettings::new_decrypted_key(
user_key,
private_key,
signing_key,
security_state,
&self.key_store,
)?;

Ok(())
}
Expand All @@ -230,8 +239,15 @@ impl InternalClient {
user_key: SymmetricCryptoKey,
private_key: EncString,
signing_key: Option<EncString>,
security_state: Option<SignedSecurityState>,
) -> Result<(), EncryptionSettingsError> {
EncryptionSettings::new_decrypted_key(user_key, private_key, signing_key, &self.key_store)?;
EncryptionSettings::new_decrypted_key(
user_key,
private_key,
signing_key,
security_state,
&self.key_store,
)?;

Ok(())
}
Expand All @@ -243,9 +259,15 @@ impl InternalClient {
pin_protected_user_key: EncString,
private_key: EncString,
signing_key: Option<EncString>,
security_state: Option<SignedSecurityState>,
) -> Result<(), EncryptionSettingsError> {
let decrypted_user_key = pin_key.decrypt_user_key(pin_protected_user_key)?;
self.initialize_user_crypto_decrypted_key(decrypted_user_key, private_key, signing_key)
self.initialize_user_crypto_decrypted_key(
decrypted_user_key,
private_key,
signing_key,
security_state,
)
}

#[cfg(feature = "secrets")]
Expand Down
2 changes: 2 additions & 0 deletions crates/bitwarden-core/src/client/test_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ pub fn test_bitwarden_com_account() -> TestAccount {
private_key: "2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse::<EncString>().unwrap().to_owned(),

signing_key: None,
security_state: None,

method: InitUserCryptoMethod::Password {
password: "asdfasdfasdf".to_owned(),
Expand Down Expand Up @@ -185,6 +186,7 @@ pub fn test_legacy_user_key_account() -> TestAccount {
email: "[email protected]".to_owned(),
private_key: "2.leBIE5u0aQUeXi++JzAnrA==|P8x+hs00RJx7epw+49qVtBhLJxE/JTL5dEHg6kq5pbZLdUY8ZvWK49v0EqgHbv1r298N9+msoO9hmdSIVIAZyycemYDSoc1rX4S1KpS/ZMA/Vd3VLFb+o13Ts62GFQ5ygHKgQZfzjU6jO5P/B/0igzFoxyJDomhW5NBC1P9+e/5qNRZN8loKvAaWc/7XtpRayPQqWx+AgYc2ntb1GF5hRVrW4M47bG5ZKllbJWtQKg2sXIy2lDBbKLRFWF4RFzNVcXQGMoPdWLY0f3uTwUH01dyGmFFMbOvfBEuYqmZyPdd93ve8zuFOEqkj46Ulpq2CVG8NvZARTwsdKl6XB0wGuHFoTsDJT2SJGl67pBBKsVRGxy059QW+9hAIB+emIV0T/7+0rvdeSXZ4AbG+oXGEXFTkHefwJKfeT0MBTAjYKr7ZRLgqvf7n39+nCEJU4l22kp8FmjcWIU7AgNipdGHC+UT2yfOcYlvgBgWDcMXcbVDMyus9105RgcW6PHozUj7yjbohI/A3XWmAFufP6BSnmEFCKoik78X/ry09xwiH2rN4KVXe/k9LpRNB2QBGIVsfgCrkxjeE8r0nA59Rvwrhny1z5BkvMW/N1KrGuafg/IYgegx72gJNuZPZlFu1Vs7HxySHmzYvm3DPV7bzCaAxxNtvZmQquNIEnsDQfjJO76iL1JCtDqNJVzGLHTMTr7S5hkOcydcH3kfKwZdA1ULVd2qu0SwOUEP/ECjU/cS5INy6WPYzNMAe/g2DISpQjNwBb5K17PIiGOR7/Q/A6E8pVnkHiAXuUFr9aLOYN9BWSu5Z+BPHH65na2FDmssix5WV09I2sUBfvdNCjkrUGdYgo8E+vOTn35x9GJHF45uhmgC1yAn/+/RSpORlrSVJ7NNP11dn3htUpSsIy/b7ituAu8Ry5mhicFU8CXJL4NeMlXThUt8P++wxs4wMkBvJ8J9NJAVKbAOA2o+GOdjbh6Ww3IRegkurWh4oL/dFSx0LpaXJuw6HFT/LzticPlSwHtUP11hZ81seMsXmkSZd8IugRFfwpPl7N6PVRWDOKxLf4gPqcnJ11TvfasXy1uolV2vZCPbrbbVzQMPdVwL/OzwfhqsIgQZI8rsDMK5D2EX8MaT8MDfGcsYcVTL9PmuZYLpOUnnHX0A1opAAa9iPw3d+eWB/GAyLvKPnMTUqVNos8HcCktXckCshihA8QuBJOwg3m0j2LPSZ5Jvf8gbXauBmt9I4IlJq0xfpgquYY1WNnO8IcWE4N9W+ASvOr9gnduA6CkDeAlyMUFmdpkeCjGMcsV741bTCPApSQlL3/TOT1cjK3iejWpz0OaVHXyg02hW2fNkOfYfr81GvnLvlHxIg4Prw89gKuWU+kQk82lFQo6QQpqbCbJC2FleurD8tYoSY0srhuioVInffvTxw2NMF7FQEqUcsK9AMKSEiDqzBi35Um/fiE3JL4XZBFw8Xzl7X3ab5nlg8X+xD5uSZY+oxD3sDVXjLaQ5JUoys+MCm0FkUj85l0zT6rvM4QLhU1RDK1U51T9HJhh8hsFJsqL4abRzwEWG7PSi859zN4UsgyuQfmBJv/n7QAFCbrJhVBlGB1TKLZRzvgmKoxTYTG3cJFkjetLcUTwrwC9naxAQRfF4=|ufHf73IzJ707dx44w4fjkuD7tDa50OwmmkxcypAT9uQ=".parse::<EncString>().unwrap().to_owned(),
signing_key: None,
security_state: None,
method: InitUserCryptoMethod::Password {
password: "asdfasdfasdf".to_owned(),
user_key: "0.8UClLa8IPE1iZT7chy5wzQ==|6PVfHnVk5S3XqEtQemnM5yb4JodxmPkkWzmDRdfyHtjORmvxqlLX40tBJZ+CKxQWmS8tpEB5w39rbgHg/gqs0haGdZG4cPbywsgGzxZ7uNI=".parse().unwrap(),
Expand Down
Loading
Loading