From 7fc33cde735705864c21f29d9524f49178ed8d06 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Sun, 21 Dec 2025 22:59:09 +0100 Subject: [PATCH 1/2] remove `InitUserCryptoMethod::Password` --- .../bitwarden-core/src/auth/auth_request.rs | 38 +++--- .../src/auth/password/validate.rs | 32 +++-- crates/bitwarden-core/src/auth/pin.rs | 18 +-- crates/bitwarden-core/src/client/internal.rs | 2 +- .../src/client/test_accounts.rs | 41 ++++--- .../src/key_management/crypto.rs | 114 ++++++++++-------- .../bitwarden-core/src/key_management/mod.rs | 4 +- .../src/platform/generate_fingerprint.rs | 28 ++--- crates/bitwarden-core/tests/register.rs | 11 +- .../src/cipher/cipher_client/share_cipher.rs | 19 ++- crates/bw/src/vault/sync.rs | 10 +- 11 files changed, 187 insertions(+), 130 deletions(-) diff --git a/crates/bitwarden-core/src/auth/auth_request.rs b/crates/bitwarden-core/src/auth/auth_request.rs index 7a16068f7..ef7e70683 100644 --- a/crates/bitwarden-core/src/auth/auth_request.rs +++ b/crates/bitwarden-core/src/auth/auth_request.rs @@ -107,13 +107,13 @@ pub(crate) fn approve_auth_request( mod tests { use std::num::NonZeroU32; - use bitwarden_crypto::{BitwardenLegacyKeyBytes, Kdf, MasterKey, SpkiPublicKeyBytes}; + use bitwarden_crypto::{BitwardenLegacyKeyBytes, Kdf, SpkiPublicKeyBytes}; use super::*; use crate::{ UserId, key_management::{ - SymmetricKeyId, + MasterPasswordUnlockData, SymmetricKeyId, account_cryptographic_state::WrappedAccountCryptographicState, crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest}, }, @@ -149,22 +149,19 @@ mod tests { fn test_approve() { let client = Client::new(None); - let master_key = MasterKey::derive( - "asdfasdfasdf", - "test@bitwarden.com", - &Kdf::PBKDF2 { - iterations: NonZeroU32::new(600_000).unwrap(), - }, - ) - .unwrap(); - let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); 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, + .initialize_user_crypto_master_password_unlock( + "asdfasdfasdf".to_string(), + MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + master_key_wrapped_user_key: user_key, + salt: "test@bitwarden.com".to_string(), + }, WrappedAccountCryptographicState::V1 { private_key }, ) .unwrap(); @@ -228,14 +225,15 @@ mod tests { // Initialize an existing client which is unlocked let existing_device = Client::new(None); - - let master_key = MasterKey::derive("asdfasdfasdf", email, &kdf).unwrap(); - existing_device .internal - .initialize_user_crypto_master_key( - master_key, - user_key, + .initialize_user_crypto_master_password_unlock( + "asdfasdfasdf".to_string(), + MasterPasswordUnlockData { + kdf: kdf.clone(), + master_key_wrapped_user_key: user_key, + salt: email.to_string(), + }, WrappedAccountCryptographicState::V1 { private_key: private_key.clone(), }, diff --git a/crates/bitwarden-core/src/auth/password/validate.rs b/crates/bitwarden-core/src/auth/password/validate.rs index ff0ad7ad8..4892bb789 100644 --- a/crates/bitwarden-core/src/auth/password/validate.rs +++ b/crates/bitwarden-core/src/auth/password/validate.rs @@ -85,7 +85,9 @@ mod tests { use crate::{ auth::password::{validate::validate_password_user_key, validate_password}, - key_management::account_cryptographic_state::WrappedAccountCryptographicState, + key_management::{ + MasterPasswordUnlockData, account_cryptographic_state::WrappedAccountCryptographicState, + }, }; #[test] @@ -119,7 +121,7 @@ mod tests { fn test_validate_password_user_key() { use std::num::NonZeroU32; - use bitwarden_crypto::{Kdf, MasterKey}; + use bitwarden_crypto::Kdf; use crate::client::{Client, LoginMethod, UserLoginMethod}; @@ -139,16 +141,18 @@ mod tests { client_id: "1".to_string(), })); - let master_key = MasterKey::derive(password, email, &kdf).unwrap(); - let user_key: EncString = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); 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.clone(), + .initialize_user_crypto_master_password_unlock( + password.to_string(), + MasterPasswordUnlockData { + kdf, + master_key_wrapped_user_key: user_key.clone(), + salt: email.to_string(), + }, WrappedAccountCryptographicState::V1 { private_key }, ) .unwrap(); @@ -169,7 +173,7 @@ mod tests { fn test_validate_password_user_key_wrong_password() { use std::num::NonZeroU32; - use bitwarden_crypto::{Kdf, MasterKey}; + use bitwarden_crypto::Kdf; use crate::client::{Client, LoginMethod, UserLoginMethod}; @@ -189,16 +193,18 @@ mod tests { client_id: "1".to_string(), })); - let master_key = MasterKey::derive(password, email, &kdf).unwrap(); - let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE="; 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.parse().unwrap(), + .initialize_user_crypto_master_password_unlock( + password.to_string(), + MasterPasswordUnlockData { + kdf, + master_key_wrapped_user_key: user_key.parse().unwrap(), + salt: email.to_string(), + }, WrappedAccountCryptographicState::V1 { private_key }, ) .unwrap(); diff --git a/crates/bitwarden-core/src/auth/pin.rs b/crates/bitwarden-core/src/auth/pin.rs index 8983fca71..2728fcad2 100644 --- a/crates/bitwarden-core/src/auth/pin.rs +++ b/crates/bitwarden-core/src/auth/pin.rs @@ -46,12 +46,14 @@ pub(crate) fn validate_pin( mod tests { use std::num::NonZeroU32; - use bitwarden_crypto::{Kdf, MasterKey}; + use bitwarden_crypto::Kdf; use super::*; use crate::{ client::{Client, LoginMethod, UserLoginMethod}, - key_management::account_cryptographic_state::WrappedAccountCryptographicState, + key_management::{ + MasterPasswordUnlockData, account_cryptographic_state::WrappedAccountCryptographicState, + }, }; fn init_client() -> Client { @@ -71,16 +73,18 @@ mod tests { client_id: "1".to_string(), })); - let master_key = MasterKey::derive(password, email, &kdf).unwrap(); - let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE="; 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.parse().unwrap(), + .initialize_user_crypto_master_password_unlock( + password.to_string(), + MasterPasswordUnlockData { + kdf, + master_key_wrapped_user_key: user_key.parse().unwrap(), + salt: email.to_string(), + }, WrappedAccountCryptographicState::V1 { private_key }, ) .unwrap(); diff --git a/crates/bitwarden-core/src/client/internal.rs b/crates/bitwarden-core/src/client/internal.rs index 74fe8307d..000836967 100644 --- a/crates/bitwarden-core/src/client/internal.rs +++ b/crates/bitwarden-core/src/client/internal.rs @@ -271,7 +271,7 @@ impl InternalClient { #[cfg(feature = "internal")] #[instrument(err, skip_all)] - pub(crate) fn initialize_user_crypto_master_key( + pub(crate) fn initialize_user_crypto_key_connector_key( &self, master_key: MasterKey, user_key: EncString, diff --git a/crates/bitwarden-core/src/client/test_accounts.rs b/crates/bitwarden-core/src/client/test_accounts.rs index 47b1a354b..913ee0ff0 100644 --- a/crates/bitwarden-core/src/client/test_accounts.rs +++ b/crates/bitwarden-core/src/client/test_accounts.rs @@ -6,6 +6,7 @@ use bitwarden_crypto::{EncString, Kdf}; use crate::{ Client, UserId, key_management::{ + MasterPasswordUnlockData, account_cryptographic_state::WrappedAccountCryptographicState, crypto::{InitOrgCryptoRequest, InitUserCryptoMethod, InitUserCryptoRequest}, }, @@ -119,19 +120,25 @@ pub struct TestAccount { /// ); /// ``` pub fn test_bitwarden_com_account() -> TestAccount { + let kdf = Kdf::PBKDF2 { + iterations: 600_000.try_into().unwrap(), + }; + let email = "test@bitwarden.com"; TestAccount { user: InitUserCryptoRequest { user_id: Some(UserId::new(uuid::uuid!("060000fb-0922-4dd3-b170-6e15cb5df8c8"))), - kdf_params: Kdf::PBKDF2 { - iterations: 600_000.try_into().unwrap(), - }, - email: "test@bitwarden.com".to_owned(), + kdf_params: kdf.clone(), + email: email.to_owned(), account_cryptographic_state: WrappedAccountCryptographicState::V1 { 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().to_owned(), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".to_owned(), - user_key: "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(), + master_password_unlock: MasterPasswordUnlockData { + kdf, + master_key_wrapped_user_key: "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(), + salt: email.to_owned(), + }, } }, org: Some(InitOrgCryptoRequest { @@ -178,21 +185,27 @@ pub fn test_bitwarden_com_account() -> TestAccount { /// ); /// ``` pub fn test_legacy_user_key_account() -> TestAccount { + let kdf = Kdf::PBKDF2 { + iterations: 600_000.try_into().unwrap(), + }; + let email = "legacy@bitwarden.com"; TestAccount { user: InitUserCryptoRequest { user_id: Some(UserId::new(uuid::uuid!("060000fb-0922-4dd3-b170-6e15cb5df8c8"))), - kdf_params: Kdf::PBKDF2 { - iterations: 600_000.try_into().unwrap(), - }, - email: "legacy@bitwarden.com".to_owned(), + kdf_params: kdf.to_owned(), + email: email.to_owned(), account_cryptographic_state: WrappedAccountCryptographicState::V1 { 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::().unwrap().to_owned(), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".to_owned(), - user_key: "0.8UClLa8IPE1iZT7chy5wzQ==|6PVfHnVk5S3XqEtQemnM5yb4JodxmPkkWzmDRdfyHtjORmvxqlLX40tBJZ+CKxQWmS8tpEB5w39rbgHg/gqs0haGdZG4cPbywsgGzxZ7uNI=".parse().unwrap(), - } + master_password_unlock: MasterPasswordUnlockData { + kdf, + master_key_wrapped_user_key: "0.8UClLa8IPE1iZT7chy5wzQ==|6PVfHnVk5S3XqEtQemnM5yb4JodxmPkkWzmDRdfyHtjORmvxqlLX40tBJZ+CKxQWmS8tpEB5w39rbgHg/gqs0haGdZG4cPbywsgGzxZ7uNI=".parse().unwrap(), + salt: email.to_owned(), + }, + }, }, -org: None, + org: None, } } diff --git a/crates/bitwarden-core/src/key_management/crypto.rs b/crates/bitwarden-core/src/key_management/crypto.rs index 8be76d1d1..cb07251aa 100644 --- a/crates/bitwarden-core/src/key_management/crypto.rs +++ b/crates/bitwarden-core/src/key_management/crypto.rs @@ -77,13 +77,6 @@ pub struct InitUserCryptoRequest { #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] #[allow(clippy::large_enum_variant)] pub enum InitUserCryptoMethod { - /// Password - Password { - /// The user's master password - password: String, - /// The user's encrypted symmetric crypto key - user_key: EncString, - }, /// Master Password Unlock MasterPasswordUnlock { /// The user's master password @@ -177,14 +170,6 @@ pub(super) async fn initialize_user_crypto( .entered(); match req.method { - InitUserCryptoMethod::Password { password, user_key } => { - let master_key = MasterKey::derive(&password, &req.email, &req.kdf_params)?; - client.internal.initialize_user_crypto_master_key( - master_key, - user_key, - account_crypto_state, - )?; - } InitUserCryptoMethod::MasterPasswordUnlock { password, master_password_unlock, @@ -265,7 +250,7 @@ pub(super) async fn initialize_user_crypto( let mut bytes = master_key.into_bytes(); let master_key = MasterKey::try_from(bytes.as_mut_slice())?; - client.internal.initialize_user_crypto_master_key( + client.internal.initialize_user_crypto_key_connector_key( master_key, user_key, account_crypto_state, @@ -954,20 +939,24 @@ mod tests { }; initialize_user_crypto( - & client, + &client, InitUserCryptoRequest { user_id: Some(UserId::new_v4()), kdf_params: kdf.clone(), email: "test@bitwarden.com".into(), account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: priv_key.to_owned() }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".into(), - user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(), + master_password_unlock: MasterPasswordUnlockData { + kdf: kdf.clone(), + master_key_wrapped_user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(), + salt: "test@bitwarden.com".to_string(), + }, }, }, ) - .await - .unwrap(); + .await + .unwrap(); let new_kdf = Kdf::PBKDF2 { iterations: 600_000.try_into().unwrap(), @@ -985,11 +974,15 @@ mod tests { account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: priv_key.to_owned(), }, - method: InitUserCryptoMethod::Password { - password: "123412341234".into(), - user_key: new_kdf_response - .master_password_unlock_data - .master_key_wrapped_user_key, + method: InitUserCryptoMethod::MasterPasswordUnlock { + password: "123412341234".to_string(), + master_password_unlock: MasterPasswordUnlockData { + kdf: new_kdf.clone(), + master_key_wrapped_user_key: new_kdf_response + .master_password_unlock_data + .master_key_wrapped_user_key, + salt: "test@bitwarden.com".to_string(), + }, }, }, ) @@ -1052,9 +1045,13 @@ mod tests { kdf_params: kdf.clone(), email: "test@bitwarden.com".into(), account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: priv_key.to_owned() }, - method: InitUserCryptoMethod::Password { - password: "asdfasdfasdf".into(), - user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(), + method: InitUserCryptoMethod::MasterPasswordUnlock { + password: "asdfasdfasdf".to_string(), + master_password_unlock: MasterPasswordUnlockData { + kdf: kdf.clone(), + master_key_wrapped_user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(), + salt: "test@bitwarden.com".to_string(), + }, }, }, ) @@ -1074,9 +1071,13 @@ mod tests { account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: priv_key.to_owned(), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "123412341234".into(), - user_key: new_password_response.new_key, + master_password_unlock: MasterPasswordUnlockData { + kdf: kdf.clone(), + master_key_wrapped_user_key: new_password_response.new_key, + salt: "test@bitwarden.com".to_string(), + }, }, }, ) @@ -1132,9 +1133,15 @@ mod tests { }, email: "test@bitwarden.com".into(), account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: priv_key.to_owned() }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".into(), - user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(), + master_password_unlock: MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }, + master_key_wrapped_user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".parse().unwrap(), + salt: "test@bitwarden.com".to_string(), + }, }, }, ) @@ -1291,22 +1298,19 @@ mod tests { fn test_enroll_admin_password_reset() { let client = Client::new(None); - let master_key = MasterKey::derive( - "asdfasdfasdf", - "test@bitwarden.com", - &Kdf::PBKDF2 { - iterations: NonZeroU32::new(600_000).unwrap(), - }, - ) - .unwrap(); - let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); 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, + .initialize_user_crypto_master_password_unlock( + "asdfasdfasdf".to_string(), + MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + master_key_wrapped_user_key: user_key, + salt: "test@bitwarden.com".to_string(), + }, WrappedAccountCryptographicState::V1 { private_key }, ) .unwrap(); @@ -1460,9 +1464,15 @@ mod tests { account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: priv_key.to_owned(), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".into(), - user_key: encrypted_userkey.clone(), + master_password_unlock: MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }, + master_key_wrapped_user_key: encrypted_userkey.clone(), + salt: "test@bitwarden.com".into(), + }, }, }, ) @@ -1499,9 +1509,15 @@ mod tests { security_state: enrollment_response.security_state, signed_public_key: Some(enrollment_response.signed_public_key), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".into(), - user_key: encrypted_userkey_v2, + master_password_unlock: MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }, + master_key_wrapped_user_key: encrypted_userkey_v2, + salt: "test@bitwarden.com".to_string(), + }, }, }, ) diff --git a/crates/bitwarden-core/src/key_management/mod.rs b/crates/bitwarden-core/src/key_management/mod.rs index bd7c140a5..aff6401e6 100644 --- a/crates/bitwarden-core/src/key_management/mod.rs +++ b/crates/bitwarden-core/src/key_management/mod.rs @@ -24,9 +24,11 @@ pub use crypto_client::CryptoClient; #[cfg(feature = "internal")] mod master_password; #[cfg(feature = "internal")] +pub(crate) use master_password::MasterPasswordAuthenticationData; +#[cfg(feature = "internal")] pub use master_password::MasterPasswordError; #[cfg(feature = "internal")] -pub(crate) use master_password::{MasterPasswordAuthenticationData, MasterPasswordUnlockData}; +pub use master_password::MasterPasswordUnlockData; #[cfg(feature = "internal")] mod security_state; #[cfg(feature = "internal")] diff --git a/crates/bitwarden-core/src/platform/generate_fingerprint.rs b/crates/bitwarden-core/src/platform/generate_fingerprint.rs index 53f2c5206..2b305bae0 100644 --- a/crates/bitwarden-core/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden-core/src/platform/generate_fingerprint.rs @@ -78,11 +78,14 @@ pub(crate) fn generate_user_fingerprint( mod tests { use std::num::NonZeroU32; - use bitwarden_crypto::{Kdf, MasterKey}; + use bitwarden_crypto::Kdf; use super::*; use crate::{ - Client, key_management::account_cryptographic_state::WrappedAccountCryptographicState, + Client, + key_management::{ + MasterPasswordUnlockData, account_cryptographic_state::WrappedAccountCryptographicState, + }, }; #[test] @@ -93,20 +96,17 @@ mod tests { let client = Client::new(None); - let master_key = MasterKey::derive( - "asdfasdfasdf", - "robb@stark.com", - &Kdf::PBKDF2 { - iterations: NonZeroU32::new(600_000).unwrap(), - }, - ) - .unwrap(); - client .internal - .initialize_user_crypto_master_key( - master_key, - user_key.parse().unwrap(), + .initialize_user_crypto_master_password_unlock( + "asdfasdfasdf".to_string(), + MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + master_key_wrapped_user_key: user_key.parse().unwrap(), + salt: "robb@stark.com".to_string(), + }, WrappedAccountCryptographicState::V1 { private_key: private_key.parse().unwrap(), }, diff --git a/crates/bitwarden-core/tests/register.rs b/crates/bitwarden-core/tests/register.rs index 5cfd1918b..6b5194088 100644 --- a/crates/bitwarden-core/tests/register.rs +++ b/crates/bitwarden-core/tests/register.rs @@ -9,6 +9,7 @@ async fn test_register_initialize_crypto() { use bitwarden_core::{ Client, UserId, key_management::{ + MasterPasswordUnlockData, account_cryptographic_state::WrappedAccountCryptographicState, crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, }, @@ -33,14 +34,18 @@ async fn test_register_initialize_crypto() { .crypto() .initialize_user_crypto(InitUserCryptoRequest { user_id: Some(UserId::new_v4()), - kdf_params: kdf, + kdf_params: kdf.clone(), email: email.to_owned(), account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: register_response.keys.private, }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: password.to_owned(), - user_key: register_response.encrypted_user_key, + master_password_unlock: MasterPasswordUnlockData { + kdf, + master_key_wrapped_user_key: register_response.encrypted_user_key, + salt: email.to_owned(), + }, }, }) .await diff --git a/crates/bitwarden-vault/src/cipher/cipher_client/share_cipher.rs b/crates/bitwarden-vault/src/cipher/cipher_client/share_cipher.rs index ed377b4e1..f5002ee00 100644 --- a/crates/bitwarden-vault/src/cipher/cipher_client/share_cipher.rs +++ b/crates/bitwarden-vault/src/cipher/cipher_client/share_cipher.rs @@ -294,8 +294,11 @@ mod tests { models::{CipherMiniResponseModelListResponseModel, CipherResponseModel}, }; use bitwarden_core::{ - Client, client::test_accounts::test_bitwarden_com_account, - key_management::account_cryptographic_state::WrappedAccountCryptographicState, + Client, + client::test_accounts::test_bitwarden_com_account, + key_management::{ + MasterPasswordUnlockData, account_cryptographic_state::WrappedAccountCryptographicState, + }, }; use bitwarden_test::{MemoryRepository, start_api_mock}; use wiremock::{ @@ -818,10 +821,16 @@ mod tests { account_cryptographic_state: WrappedAccountCryptographicState::V1 { 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(), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: "asdfasdfasdf".to_owned(), - user_key: "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(), - } + master_password_unlock: MasterPasswordUnlockData { + kdf: Kdf::PBKDF2 { + iterations: 600_000.try_into().unwrap(), + }, + master_key_wrapped_user_key: "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(), + salt: "test@bitwarden.com".to_owned(), + }, + }, }; let org_request = InitOrgCryptoRequest { diff --git a/crates/bw/src/vault/sync.rs b/crates/bw/src/vault/sync.rs index b7b8107e8..1b4a964fe 100644 --- a/crates/bw/src/vault/sync.rs +++ b/crates/bw/src/vault/sync.rs @@ -197,7 +197,7 @@ mod tests { use bitwarden_core::{ ClientSettings, DeviceType, key_management::{ - SymmetricKeyId, + MasterPasswordUnlockData, SymmetricKeyId, account_cryptographic_state::WrappedAccountCryptographicState, crypto::{InitOrgCryptoRequest, InitUserCryptoMethod, InitUserCryptoRequest}, }, @@ -286,9 +286,13 @@ mod tests { account_cryptographic_state: WrappedAccountCryptographicState::V1 { private_key: TEST_ACCOUNT_PRIVATE_KEY.parse().unwrap(), }, - method: InitUserCryptoMethod::Password { + method: InitUserCryptoMethod::MasterPasswordUnlock { password: TEST_USER_PASSWORD.to_string(), - user_key: TEST_ACCOUNT_USER_KEY.parse().unwrap(), + master_password_unlock: MasterPasswordUnlockData { + kdf: Kdf::default(), + master_key_wrapped_user_key: TEST_ACCOUNT_USER_KEY.parse().unwrap(), + salt: TEST_USER_EMAIL.to_string(), + }, }, } } From 2fb654ceed50b03e31c10ee91d29288f86911fe5 Mon Sep 17 00:00:00 2001 From: Maciej Zieniuk Date: Sun, 21 Dec 2025 23:44:09 +0100 Subject: [PATCH 2/2] updated kotlin, swift example apps --- .../java/com/bitwarden/myapplication/MainActivity.kt | 10 ++++++++-- .../bitwarden-uniffi/swift/iOS/App/ContentView.swift | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/bitwarden-uniffi/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/crates/bitwarden-uniffi/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index 0482c4137..5aef523e2 100644 --- a/crates/bitwarden-uniffi/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/crates/bitwarden-uniffi/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -28,6 +28,7 @@ import com.bitwarden.vault.Folder import com.bitwarden.core.InitOrgCryptoRequest import com.bitwarden.core.InitUserCryptoMethod import com.bitwarden.core.InitUserCryptoRequest +import com.bitwarden.core.MasterPasswordUnlockData import com.bitwarden.core.WrappedAccountCryptographicState import com.bitwarden.core.Uuid import com.bitwarden.crypto.HashPurpose @@ -261,8 +262,13 @@ class MainActivity : FragmentActivity() { kdfParams = kdf, email = EMAIL, accountCryptographicState = WrappedAccountCryptographicState.V1(privateKey = loginBody.PrivateKey), - method = InitUserCryptoMethod.Password( - password = PASSWORD, userKey = loginBody.Key + method = InitUserCryptoMethod.MasterPasswordUnlock( + password = PASSWORD, + masterPasswordUnlock = MasterPasswordUnlockData( + kdf = kdf, + masterKeyWrappedUserKey = loginBody.Key, + salt = EMAIL + ) ) ) ) diff --git a/crates/bitwarden-uniffi/swift/iOS/App/ContentView.swift b/crates/bitwarden-uniffi/swift/iOS/App/ContentView.swift index 2158b9b88..acd3e5548 100644 --- a/crates/bitwarden-uniffi/swift/iOS/App/ContentView.swift +++ b/crates/bitwarden-uniffi/swift/iOS/App/ContentView.swift @@ -195,9 +195,13 @@ struct ContentView: View { kdfParams: kdf, email: EMAIL, accountCryptographicState: WrappedAccountCryptographicState.v1(privateKey: loginData.PrivateKey), - method: InitUserCryptoMethod.password( + method: InitUserCryptoMethod.masterPasswordUnlock( password: PASSWORD, - userKey: loginData.Key + masterPasswordUnlock: MasterPasswordUnlockData( + kdf: kdf, + masterKeyWrappedUserKey: loginData.Key, + salt: EMAIL + ) ) ))