From 6811df267ba041b4ae2fe5e5f98c679c17dda69f Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 26 May 2025 10:59:03 +0200 Subject: [PATCH 1/8] Add UserId, CipherId, FolderId --- Cargo.lock | 1 + .../bitwarden-core/src/auth/auth_request.rs | 3 +- .../src/auth/login/access_token.rs | 9 +- .../src/client/encryption_settings.rs | 12 +-- crates/bitwarden-core/src/client/internal.rs | 26 +++--- .../bitwarden-core/src/client/login_method.rs | 8 +- .../src/client/test_accounts.rs | 6 +- crates/bitwarden-core/src/ids.rs | 5 +- crates/bitwarden-core/src/mobile/crypto.rs | 16 ++-- crates/bitwarden-core/tests/register.rs | 4 +- crates/bitwarden-exporters/src/lib.rs | 4 +- crates/bitwarden-exporters/src/models.rs | 14 +-- crates/bitwarden-fido/src/types.rs | 6 +- crates/bitwarden-uniffi/src/vault/ciphers.rs | 5 +- crates/bitwarden-uuid-macro/src/lib.rs | 9 +- crates/bitwarden-uuid/src/lib.rs | 2 +- crates/bitwarden-uuid/tests/uuid.rs | 4 +- crates/bitwarden-vault/Cargo.toml | 3 +- crates/bitwarden-vault/src/cipher/cipher.rs | 85 ++++++++++--------- .../src/cipher/cipher_client.rs | 2 +- crates/bitwarden-vault/src/cipher/mod.rs | 4 +- crates/bitwarden-vault/src/collection.rs | 20 +++-- crates/bitwarden-vault/src/folder.rs | 10 ++- crates/bitwarden-vault/src/lib.rs | 4 +- crates/bitwarden-vault/src/sync.rs | 11 +-- 25 files changed, 150 insertions(+), 123 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec14e3089..7ac5a0648 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -647,6 +647,7 @@ dependencies = [ "bitwarden-core", "bitwarden-crypto", "bitwarden-error", + "bitwarden-uuid", "chrono", "data-encoding", "hmac", diff --git a/crates/bitwarden-core/src/auth/auth_request.rs b/crates/bitwarden-core/src/auth/auth_request.rs index 4b7fb54e0..69673338e 100644 --- a/crates/bitwarden-core/src/auth/auth_request.rs +++ b/crates/bitwarden-core/src/auth/auth_request.rs @@ -143,6 +143,7 @@ mod tests { use crate::{ key_management::SymmetricKeyId, mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest}, + UserId, }; #[test] @@ -243,7 +244,7 @@ mod tests { new_device .crypto() .initialize_user_crypto(InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: kdf, email: email.to_owned(), private_key: private_key.to_owned(), diff --git a/crates/bitwarden-core/src/auth/login/access_token.rs b/crates/bitwarden-core/src/auth/login/access_token.rs index 66a777bef..c0596e7cb 100644 --- a/crates/bitwarden-core/src/auth/login/access_token.rs +++ b/crates/bitwarden-core/src/auth/login/access_token.rs @@ -5,7 +5,6 @@ use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; use chrono::Utc; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use super::LoginError; use crate::{ @@ -17,7 +16,7 @@ use crate::{ client::{LoginMethod, ServiceAccountLoginMethod}, require, secrets_manager::state::{self, ClientState}, - Client, + Client, OrganizationId, }; pub(crate) async fn login_access_token( @@ -36,7 +35,7 @@ pub(crate) async fn login_access_token( .set_login_method(LoginMethod::ServiceAccount( ServiceAccountLoginMethod::AccessToken { access_token, - organization_id, + organization_id: organization_id.into(), state_file: Some(state_file.to_path_buf()), }, )); @@ -118,7 +117,7 @@ fn load_tokens_from_state( client: &Client, state_file: &Path, access_token: &AccessToken, -) -> Result { +) -> Result { let client_state = state::get(state_file, access_token)?; let token: JwtToken = client_state.token.parse()?; @@ -127,7 +126,7 @@ fn load_tokens_from_state( let time_till_expiration = (token.exp as i64) - Utc::now().timestamp(); if time_till_expiration > 0 { - let organization_id: Uuid = organization_id + let organization_id: OrganizationId = organization_id .parse() .map_err(|_| LoginError::InvalidOrganizationId)?; let encryption_key = SymmetricCryptoKey::try_from(client_state.encryption_key)?; diff --git a/crates/bitwarden-core/src/client/encryption_settings.rs b/crates/bitwarden-core/src/client/encryption_settings.rs index 649be0351..9a4baf596 100644 --- a/crates/bitwarden-core/src/client/encryption_settings.rs +++ b/crates/bitwarden-core/src/client/encryption_settings.rs @@ -3,7 +3,9 @@ use bitwarden_crypto::{AsymmetricCryptoKey, KeyStore, SymmetricCryptoKey}; use bitwarden_crypto::{EncString, UnsignedSharedKey}; use bitwarden_error::bitwarden_error; use thiserror::Error; -use uuid::Uuid; + +#[cfg(any(feature = "secrets", feature = "internal"))] +use crate::OrganizationId; use crate::{ error::UserIdAlreadySetError, @@ -85,7 +87,7 @@ impl EncryptionSettings { /// This is used only for logging in Secrets Manager with an access token #[cfg(feature = "secrets")] pub(crate) fn new_single_org_key( - organization_id: Uuid, + organization_id: OrganizationId, key: SymmetricCryptoKey, store: &KeyStore, ) { @@ -93,13 +95,13 @@ impl EncryptionSettings { #[allow(deprecated)] store .context_mut() - .set_symmetric_key(SymmetricKeyId::Organization(organization_id), key) + .set_symmetric_key(SymmetricKeyId::Organization(organization_id.into()), key) .expect("Mutable context"); } #[cfg(feature = "internal")] pub(crate) fn set_org_keys( - org_enc_keys: Vec<(Uuid, UnsignedSharedKey)>, + org_enc_keys: Vec<(OrganizationId, UnsignedSharedKey)>, store: &KeyStore, ) -> Result<(), EncryptionSettingsError> { let mut ctx = store.context_mut(); @@ -121,7 +123,7 @@ impl EncryptionSettings { for (org_id, org_enc_key) in org_enc_keys { ctx.decapsulate_key_unsigned( AsymmetricKeyId::UserPrivateKey, - SymmetricKeyId::Organization(org_id), + SymmetricKeyId::Organization(org_id.into()), &org_enc_key, )?; } diff --git a/crates/bitwarden-core/src/client/internal.rs b/crates/bitwarden-core/src/client/internal.rs index 34999e25f..65f3ad982 100644 --- a/crates/bitwarden-core/src/client/internal.rs +++ b/crates/bitwarden-core/src/client/internal.rs @@ -6,7 +6,6 @@ use bitwarden_crypto::SymmetricCryptoKey; #[cfg(feature = "internal")] use bitwarden_crypto::{EncString, Kdf, MasterKey, PinKey, UnsignedSharedKey}; use chrono::Utc; -use uuid::Uuid; #[cfg(feature = "secrets")] use super::login_method::ServiceAccountLoginMethod; @@ -15,13 +14,14 @@ use crate::{ client::{encryption_settings::EncryptionSettings, login_method::LoginMethod}, error::UserIdAlreadySetError, key_management::KeyIds, - DeviceType, + DeviceType, UserId, }; #[cfg(feature = "internal")] use crate::{ client::encryption_settings::EncryptionSettingsError, client::{flags::Flags, login_method::UserLoginMethod}, error::NotAuthenticatedError, + OrganizationId, }; #[derive(Debug, Clone)] @@ -45,7 +45,7 @@ pub(crate) struct Tokens { #[derive(Debug)] pub struct InternalClient { - pub(crate) user_id: OnceLock, + pub(crate) user_id: OnceLock, pub(crate) tokens: RwLock, pub(crate) login_method: RwLock>>, @@ -83,7 +83,7 @@ impl InternalClient { .clone() } - pub fn get_access_token_organization(&self) -> Option { + pub fn get_access_token_organization(&self) -> Option { match self .login_method .read() @@ -174,11 +174,11 @@ impl InternalClient { &self.key_store } - pub fn init_user_id(&self, user_id: Uuid) -> Result<(), UserIdAlreadySetError> { + pub fn init_user_id(&self, user_id: UserId) -> Result<(), UserIdAlreadySetError> { self.user_id.set(user_id).map_err(|_| UserIdAlreadySetError) } - pub fn get_user_id(&self) -> Option { + pub fn get_user_id(&self) -> Option { self.user_id.get().copied() } @@ -220,17 +220,23 @@ impl InternalClient { #[cfg(feature = "secrets")] pub(crate) fn initialize_crypto_single_org_key( &self, - organization_id: Uuid, + organization_id: OrganizationId, key: SymmetricCryptoKey, ) { - EncryptionSettings::new_single_org_key(organization_id, key, &self.key_store); + EncryptionSettings::new_single_org_key(organization_id.into(), key, &self.key_store); } #[cfg(feature = "internal")] pub fn initialize_org_crypto( &self, - org_keys: Vec<(Uuid, UnsignedSharedKey)>, + org_keys: Vec<(OrganizationId, UnsignedSharedKey)>, ) -> Result<(), EncryptionSettingsError> { - EncryptionSettings::set_org_keys(org_keys, &self.key_store) + EncryptionSettings::set_org_keys( + org_keys + .into_iter() + .map(|(id, key)| (id.into(), key)) + .collect(), + &self.key_store, + ) } } diff --git a/crates/bitwarden-core/src/client/login_method.rs b/crates/bitwarden-core/src/client/login_method.rs index 67db15a71..84f64a653 100644 --- a/crates/bitwarden-core/src/client/login_method.rs +++ b/crates/bitwarden-core/src/client/login_method.rs @@ -1,12 +1,10 @@ #[cfg(feature = "secrets")] use std::path::PathBuf; -use bitwarden_crypto::Kdf; -#[cfg(feature = "secrets")] -use uuid::Uuid; - #[cfg(feature = "secrets")] use crate::auth::AccessToken; +use crate::OrganizationId; +use bitwarden_crypto::Kdf; #[derive(Debug)] pub(crate) enum LoginMethod { @@ -40,7 +38,7 @@ pub(crate) enum UserLoginMethod { pub(crate) enum ServiceAccountLoginMethod { AccessToken { access_token: AccessToken, - organization_id: Uuid, + organization_id: OrganizationId, state_file: Option, }, } diff --git a/crates/bitwarden-core/src/client/test_accounts.rs b/crates/bitwarden-core/src/client/test_accounts.rs index 7694cfa8e..f1f91b625 100644 --- a/crates/bitwarden-core/src/client/test_accounts.rs +++ b/crates/bitwarden-core/src/client/test_accounts.rs @@ -8,7 +8,7 @@ use crate::{ initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoMethod, InitUserCryptoRequest, }, - Client, + Client, UserId, }; impl Client { @@ -117,7 +117,7 @@ pub struct TestAccount { pub fn test_bitwarden_com_account() -> TestAccount { TestAccount { user: InitUserCryptoRequest { - user_id: Some(uuid::uuid!("060000fb-0922-4dd3-b170-6e15cb5df8c8")), + user_id: Some(UserId::new(uuid::uuid!("060000fb-0922-4dd3-b170-6e15cb5df8c8"))), kdf_params: Kdf::PBKDF2 { iterations: 600_000.try_into().unwrap(), }, @@ -175,7 +175,7 @@ pub fn test_bitwarden_com_account() -> TestAccount { pub fn test_legacy_user_key_account() -> TestAccount { TestAccount { user: InitUserCryptoRequest { - user_id: Some(uuid::uuid!("060000fb-0922-4dd3-b170-6e15cb5df8c8")), + user_id: Some(UserId::new(uuid::uuid!("060000fb-0922-4dd3-b170-6e15cb5df8c8"))), kdf_params: Kdf::PBKDF2 { iterations: 600_000.try_into().unwrap(), }, diff --git a/crates/bitwarden-core/src/ids.rs b/crates/bitwarden-core/src/ids.rs index e86527044..ec010cdbc 100644 --- a/crates/bitwarden-core/src/ids.rs +++ b/crates/bitwarden-core/src/ids.rs @@ -1,3 +1,4 @@ -use bitwarden_uuid::uuid; +use bitwarden_uuid::uuid_newtype; -uuid!(pub OrganizationId); +uuid_newtype!(pub OrganizationId); +uuid_newtype!(pub UserId); diff --git a/crates/bitwarden-core/src/mobile/crypto.rs b/crates/bitwarden-core/src/mobile/crypto.rs index 60cbe1a8a..d2b6adf6a 100644 --- a/crates/bitwarden-core/src/mobile/crypto.rs +++ b/crates/bitwarden-core/src/mobile/crypto.rs @@ -18,7 +18,7 @@ use {tsify_next::Tsify, wasm_bindgen::prelude::*}; use crate::{ client::{encryption_settings::EncryptionSettingsError, LoginMethod, UserLoginMethod}, key_management::SymmetricKeyId, - Client, NotAuthenticatedError, VaultLockedError, WrongPasswordError, + Client, NotAuthenticatedError, OrganizationId, UserId, VaultLockedError, WrongPasswordError, }; /// Catch all error for mobile crypto operations. @@ -39,7 +39,7 @@ pub enum MobileCryptoError { #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct InitUserCryptoRequest { - pub user_id: Option, + pub user_id: Option, /// The user's KDF parameters, as received from the prelogin request pub kdf_params: Kdf, /// The user's email address @@ -232,7 +232,7 @@ pub async fn initialize_user_crypto( #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct InitOrgCryptoRequest { /// The encryption keys for all the organizations the user is a part of - pub organization_keys: HashMap, + pub organization_keys: HashMap, } /// Initialize the user's organizational cryptographic state. @@ -569,7 +569,7 @@ mod tests { initialize_user_crypto( & client, InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: kdf.clone(), email: "test@bitwarden.com".into(), private_key: priv_key.to_owned(), @@ -589,7 +589,7 @@ mod tests { initialize_user_crypto( &client2, InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: kdf.clone(), email: "test@bitwarden.com".into(), private_key: priv_key.to_owned(), @@ -645,7 +645,7 @@ mod tests { initialize_user_crypto( & client, InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: Kdf::PBKDF2 { iterations: 100_000.try_into().unwrap(), }, @@ -667,7 +667,7 @@ mod tests { initialize_user_crypto( &client2, InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: Kdf::PBKDF2 { iterations: 100_000.try_into().unwrap(), }, @@ -710,7 +710,7 @@ mod tests { initialize_user_crypto( &client3, InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: Kdf::PBKDF2 { iterations: 100_000.try_into().unwrap(), }, diff --git a/crates/bitwarden-core/tests/register.rs b/crates/bitwarden-core/tests/register.rs index 9f9e9c815..38e917d87 100644 --- a/crates/bitwarden-core/tests/register.rs +++ b/crates/bitwarden-core/tests/register.rs @@ -8,7 +8,7 @@ async fn test_register_initialize_crypto() { use bitwarden_core::{ mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, - Client, + Client, UserId, }; use bitwarden_crypto::Kdf; @@ -29,7 +29,7 @@ async fn test_register_initialize_crypto() { client .crypto() .initialize_user_crypto(InitUserCryptoRequest { - user_id: Some(uuid::Uuid::new_v4()), + user_id: Some(UserId::new_v4()), kdf_params: kdf, email: email.to_owned(), private_key: register_response.keys.private.to_string(), diff --git a/crates/bitwarden-exporters/src/lib.rs b/crates/bitwarden-exporters/src/lib.rs index 634d604c2..e70ee16f2 100644 --- a/crates/bitwarden-exporters/src/lib.rs +++ b/crates/bitwarden-exporters/src/lib.rs @@ -1,7 +1,7 @@ use std::fmt; use bitwarden_vault::{ - CipherRepromptType, CipherView, Fido2CredentialFullView, LoginUriView, UriMatchType, + CipherRepromptType, CipherView, Fido2CredentialFullView, FolderId, LoginUriView, UriMatchType, }; use chrono::{DateTime, Utc}; use uuid::Uuid; @@ -117,7 +117,7 @@ impl From for CipherView { Self { id: None, organization_id: None, - folder_id: value.folder_id, + folder_id: value.folder_id.map(FolderId::new), collection_ids: vec![], key: None, name: value.name, diff --git a/crates/bitwarden-exporters/src/models.rs b/crates/bitwarden-exporters/src/models.rs index 97e19c059..3bc3a85c4 100644 --- a/crates/bitwarden-exporters/src/models.rs +++ b/crates/bitwarden-exporters/src/models.rs @@ -10,7 +10,7 @@ impl TryFrom for crate::Folder { fn try_from(value: FolderView) -> Result { Ok(Self { - id: require!(value.id), + id: require!(value.id).into(), name: value.name, }) } @@ -44,8 +44,8 @@ impl crate::Cipher { }; Ok(Self { - id: require!(view.id), - folder_id: view.folder_id, + id: require!(view.id).into(), + folder_id: view.folder_id.map(|f| f.into()), name: view.name, notes: view.notes, r#type: r, @@ -200,7 +200,7 @@ impl From for crate::SecureNoteType { mod tests { use bitwarden_core::key_management::create_test_crypto_with_user_key; use bitwarden_crypto::SymmetricCryptoKey; - use bitwarden_vault::{CipherRepromptType, LoginView}; + use bitwarden_vault::{CipherId, CipherRepromptType, FolderId, LoginView}; use chrono::{DateTime, Utc}; use super::*; @@ -209,7 +209,7 @@ mod tests { fn test_try_from_folder_view() { let test_id: uuid::Uuid = "fd411a1a-fec8-4070-985d-0e6560860e69".parse().unwrap(); let view = FolderView { - id: Some(test_id), + id: Some(FolderId::new(test_id)), name: "test_name".to_string(), revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), }; @@ -237,7 +237,7 @@ mod tests { autofill_on_page_load: None, fido2_credentials: None, }), - id: Some(test_id), + id: Some(CipherId::new(test_id)), organization_id: None, folder_id: None, collection_ids: vec![], @@ -288,7 +288,7 @@ mod tests { autofill_on_page_load: None, fido2_credentials: None, }), - id: Some(test_id), + id: Some(CipherId::new(test_id)), organization_id: None, folder_id: None, collection_ids: vec![], diff --git a/crates/bitwarden-fido/src/types.rs b/crates/bitwarden-fido/src/types.rs index ae92ca378..9b2eb3386 100644 --- a/crates/bitwarden-fido/src/types.rs +++ b/crates/bitwarden-fido/src/types.rs @@ -80,7 +80,8 @@ impl Fido2CredentialAutofillView { credential_id: string_to_guid_bytes(&c.credential_id)?, cipher_id: cipher .id - .ok_or(Fido2CredentialAutofillViewError::MissingCipherId)?, + .ok_or(Fido2CredentialAutofillViewError::MissingCipherId)? + .into(), rp_id: c.rp_id.clone(), user_handle: user_handle?, user_name_for_ui: c @@ -117,7 +118,8 @@ impl Fido2CredentialAutofillView { credential_id: string_to_guid_bytes(&c.credential_id)?, cipher_id: cipher .id - .ok_or(Fido2CredentialAutofillViewError::MissingCipherId)?, + .ok_or(Fido2CredentialAutofillViewError::MissingCipherId)? + .into(), rp_id: c.rp_id.clone(), user_handle: user_handle?, user_name_for_ui: c diff --git a/crates/bitwarden-uniffi/src/vault/ciphers.rs b/crates/bitwarden-uniffi/src/vault/ciphers.rs index e1002da97..e6c92d99b 100644 --- a/crates/bitwarden-uniffi/src/vault/ciphers.rs +++ b/crates/bitwarden-uniffi/src/vault/ciphers.rs @@ -1,6 +1,5 @@ use bitwarden_core::OrganizationId; use bitwarden_vault::{Cipher, CipherListView, CipherView, EncryptionContext, Fido2CredentialView}; -use uuid::Uuid; use crate::{error::Error, Result}; @@ -38,11 +37,11 @@ impl CiphersClient { pub fn move_to_organization( &self, cipher: CipherView, - organization_id: Uuid, + organization_id: OrganizationId, ) -> Result { Ok(self .0 - .move_to_organization(cipher, OrganizationId::new(organization_id)) + .move_to_organization(cipher, organization_id) .map_err(Error::Cipher)?) } } diff --git a/crates/bitwarden-uuid-macro/src/lib.rs b/crates/bitwarden-uuid-macro/src/lib.rs index 87ebbab47..63dc108e3 100644 --- a/crates/bitwarden-uuid-macro/src/lib.rs +++ b/crates/bitwarden-uuid-macro/src/lib.rs @@ -8,7 +8,7 @@ use syn::{ }; #[proc_macro] -pub fn uuid(input: TokenStream) -> TokenStream { +pub fn uuid_newtype(input: TokenStream) -> TokenStream { // Parse input as: vis ident let input = parse_macro_input!(input as IdTypeInput); let ident = input.ident; @@ -23,7 +23,7 @@ pub fn uuid(input: TokenStream) -> TokenStream { #[cfg_attr(feature = "wasm", derive(::tsify_next::Tsify), tsify(into_wasm_abi, from_wasm_abi))] #[derive( ::serde::Serialize, ::serde::Deserialize, - ::std::cmp::PartialEq, ::std::cmp::Eq, + ::std::cmp::PartialEq, ::std::cmp::Eq, ::std::hash::Hash, ::std::clone::Clone, ::std::marker::Copy, ::std::fmt::Debug )] #[repr(transparent)] @@ -40,6 +40,11 @@ pub fn uuid(input: TokenStream) -> TokenStream { pub fn new(value: uuid::Uuid) -> Self { Self(value) } + + /// Create a new UUID v4 based id. + pub fn new_v4() -> Self { + Self(uuid::Uuid::new_v4()) + } } impl ::std::str::FromStr for #ident { diff --git a/crates/bitwarden-uuid/src/lib.rs b/crates/bitwarden-uuid/src/lib.rs index 870be9095..3cc268215 100644 --- a/crates/bitwarden-uuid/src/lib.rs +++ b/crates/bitwarden-uuid/src/lib.rs @@ -1,3 +1,3 @@ #![doc = include_str!("../README.md")] -pub use bitwarden_uuid_macro::uuid; +pub use bitwarden_uuid_macro::uuid_newtype; diff --git a/crates/bitwarden-uuid/tests/uuid.rs b/crates/bitwarden-uuid/tests/uuid.rs index 519829d10..fae4cc64b 100644 --- a/crates/bitwarden-uuid/tests/uuid.rs +++ b/crates/bitwarden-uuid/tests/uuid.rs @@ -1,8 +1,8 @@ #![allow(unexpected_cfgs)] -use bitwarden_uuid::uuid; +use bitwarden_uuid::uuid_newtype; -uuid!(TestId); +uuid_newtype!(TestId); #[test] fn test_parse_string() { diff --git a/crates/bitwarden-vault/Cargo.toml b/crates/bitwarden-vault/Cargo.toml index d04aa7df3..1f582ceb0 100644 --- a/crates/bitwarden-vault/Cargo.toml +++ b/crates/bitwarden-vault/Cargo.toml @@ -18,7 +18,7 @@ keywords.workspace = true uniffi = [ "bitwarden-core/uniffi", "bitwarden-crypto/uniffi", - "dep:uniffi" + "dep:uniffi", ] # Uniffi bindings wasm = ["dep:tsify-next", "dep:wasm-bindgen"] # WASM support @@ -28,6 +28,7 @@ bitwarden-api-api = { workspace = true } bitwarden-core = { workspace = true, features = ["internal"] } bitwarden-crypto = { workspace = true } bitwarden-error = { workspace = true } +bitwarden-uuid = { workspace = true } chrono = { workspace = true } data-encoding = ">=2.0, <3" hmac = ">=0.12.1, <0.13" diff --git a/crates/bitwarden-vault/src/cipher/cipher.rs b/crates/bitwarden-vault/src/cipher/cipher.rs index ee1f640fb..c5c0ff992 100644 --- a/crates/bitwarden-vault/src/cipher/cipher.rs +++ b/crates/bitwarden-vault/src/cipher/cipher.rs @@ -1,19 +1,19 @@ use bitwarden_api_api::models::CipherDetailsResponseModel; use bitwarden_core::{ key_management::{KeyIds, SymmetricKeyId}, - require, MissingFieldError, VaultLockedError, + require, MissingFieldError, OrganizationId, UserId, VaultLockedError, }; use bitwarden_crypto::{ CryptoError, Decryptable, EncString, Encryptable, IdentifyKey, KeyStoreContext, }; use bitwarden_error::bitwarden_error; +use bitwarden_uuid::uuid_newtype; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use thiserror::Error; #[cfg(feature = "wasm")] use tsify_next::Tsify; -use uuid::Uuid; #[cfg(feature = "wasm")] use wasm_bindgen::prelude::wasm_bindgen; @@ -26,10 +26,12 @@ use super::{ secure_note, ssh_key, }; use crate::{ - password_history, Fido2CredentialFullView, Fido2CredentialView, Login, LoginView, - VaultParseError, + password_history, CollectionId, Fido2CredentialFullView, Fido2CredentialView, FolderId, Login, + LoginView, VaultParseError, }; +uuid_newtype!(pub CipherId); + #[bitwarden_error(flat)] #[derive(Debug, Error)] pub enum CipherError { @@ -71,7 +73,7 @@ pub enum CipherRepromptType { pub struct EncryptionContext { /// The Id of the user that encrypted the cipher. It should always represent a UserId, even for /// Organization-owned ciphers - pub encrypted_for: Uuid, + pub encrypted_for: UserId, pub cipher: Cipher, } @@ -80,10 +82,10 @@ pub struct EncryptionContext { #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct Cipher { - pub id: Option, - pub organization_id: Option, - pub folder_id: Option, - pub collection_ids: Vec, + pub id: Option, + pub organization_id: Option, + pub folder_id: Option, + pub collection_ids: Vec, /// More recent ciphers uses individual encryption keys to encrypt the other fields of the /// Cipher. @@ -121,10 +123,10 @@ pub struct Cipher { #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct CipherView { - pub id: Option, - pub organization_id: Option, - pub folder_id: Option, - pub collection_ids: Vec, + pub id: Option, + pub organization_id: Option, + pub folder_id: Option, + pub collection_ids: Vec, /// Temporary, required to support re-encrypting existing items. pub key: Option, @@ -173,10 +175,10 @@ pub enum CipherListViewType { #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct CipherListView { - pub id: Option, - pub organization_id: Option, - pub folder_id: Option, - pub collection_ids: Vec, + pub id: Option, + pub organization_id: Option, + pub folder_id: Option, + pub collection_ids: Vec, /// Temporary, required to support calculating TOTP from CipherListView. pub key: Option, @@ -543,10 +545,10 @@ impl CipherView { pub fn move_to_organization( &mut self, ctx: &mut KeyStoreContext, - organization_id: Uuid, + organization_id: OrganizationId, ) -> Result<(), CipherError> { let old_key = self.key_identifier(); - let new_key = SymmetricKeyId::Organization(organization_id); + let new_key = SymmetricKeyId::Organization(organization_id.into()); // If any attachment is missing a key we can't reencrypt the attachment keys if self.attachments.iter().flatten().any(|a| a.key.is_none()) { @@ -658,7 +660,7 @@ impl Decryptable for Cipher { impl IdentifyKey for Cipher { fn key_identifier(&self) -> SymmetricKeyId { match self.organization_id { - Some(organization_id) => SymmetricKeyId::Organization(organization_id), + Some(organization_id) => SymmetricKeyId::Organization(organization_id.into()), None => SymmetricKeyId::User, } } @@ -667,7 +669,7 @@ impl IdentifyKey for Cipher { impl IdentifyKey for CipherView { fn key_identifier(&self) -> SymmetricKeyId { match self.organization_id { - Some(organization_id) => SymmetricKeyId::Organization(organization_id), + Some(organization_id) => SymmetricKeyId::Organization(organization_id.into()), None => SymmetricKeyId::User, } } @@ -676,7 +678,7 @@ impl IdentifyKey for CipherView { impl IdentifyKey for CipherListView { fn key_identifier(&self) -> SymmetricKeyId { match self.organization_id { - Some(organization_id) => SymmetricKeyId::Organization(organization_id), + Some(organization_id) => SymmetricKeyId::Organization(organization_id.into()), None => SymmetricKeyId::User, } } @@ -687,10 +689,15 @@ impl TryFrom for Cipher { fn try_from(cipher: CipherDetailsResponseModel) -> Result { Ok(Self { - id: cipher.id, - organization_id: cipher.organization_id, - folder_id: cipher.folder_id, - collection_ids: cipher.collection_ids.unwrap_or_default(), + id: cipher.id.map(CipherId::new), + organization_id: cipher.organization_id.map(OrganizationId::new), + folder_id: cipher.folder_id.map(FolderId::new), + collection_ids: cipher + .collection_ids + .unwrap_or_default() + .into_iter() + .map(CollectionId::new) + .collect(), name: require!(EncString::try_from_optional(cipher.name)?), notes: EncString::try_from_optional(cipher.notes)?, r#type: require!(cipher.r#type).into(), @@ -766,7 +773,7 @@ mod tests { use crate::{login::Fido2CredentialListView, Fido2Credential}; fn generate_cipher() -> CipherView { - let test_id: uuid::Uuid = "fd411a1a-fec8-4070-985d-0e6560860e69".parse().unwrap(); + let test_id = "fd411a1a-fec8-4070-985d-0e6560860e69".parse().unwrap(); CipherView { r#type: CipherType::Login, login: Some(LoginView { @@ -986,10 +993,10 @@ mod tests { #[test] fn test_move_user_cipher_to_org() { - let org = uuid::Uuid::new_v4(); + let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); + let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); // Create a cipher with a user key let mut cipher = generate_cipher(); @@ -1011,10 +1018,10 @@ mod tests { #[test] fn test_move_user_cipher_to_org_manually() { - let org = uuid::Uuid::new_v4(); + let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); + let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); // Create a cipher with a user key let mut cipher = generate_cipher(); @@ -1031,10 +1038,10 @@ mod tests { #[test] fn test_move_user_cipher_with_attachment_without_key_to_org() { - let org = uuid::Uuid::new_v4(); + let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); + let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); let mut cipher = generate_cipher(); let attachment = AttachmentView { @@ -1055,11 +1062,11 @@ mod tests { #[test] fn test_move_user_cipher_with_attachment_with_key_to_org() { - let org = uuid::Uuid::new_v4(); + let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); - let org_key = SymmetricKeyId::Organization(org); + let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); + let org_key = SymmetricKeyId::Organization(org.into()); // Attachment has a key that is encrypted with the user key, as the cipher has no key itself let (attachment_key_enc, attachment_key_val) = { @@ -1123,11 +1130,11 @@ mod tests { #[test] fn test_move_user_cipher_with_key_with_attachment_with_key_to_org() { - let org = uuid::Uuid::new_v4(); + let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); - let org_key = SymmetricKeyId::Organization(org); + let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); + let org_key = SymmetricKeyId::Organization(org.into()); let mut ctx = key_store.context(); diff --git a/crates/bitwarden-vault/src/cipher/cipher_client.rs b/crates/bitwarden-vault/src/cipher/cipher_client.rs index e347302e5..dc8db0a64 100644 --- a/crates/bitwarden-vault/src/cipher/cipher_client.rs +++ b/crates/bitwarden-vault/src/cipher/cipher_client.rs @@ -70,7 +70,7 @@ impl CiphersClient { organization_id: OrganizationId, ) -> Result { let key_store = self.client.internal.get_key_store(); - cipher_view.move_to_organization(&mut key_store.context(), organization_id.into())?; + cipher_view.move_to_organization(&mut key_store.context(), organization_id)?; Ok(cipher_view) } diff --git a/crates/bitwarden-vault/src/cipher/mod.rs b/crates/bitwarden-vault/src/cipher/mod.rs index 8f3a16f11..9197d4916 100644 --- a/crates/bitwarden-vault/src/cipher/mod.rs +++ b/crates/bitwarden-vault/src/cipher/mod.rs @@ -19,8 +19,8 @@ pub use attachment::{ pub use attachment_client::{AttachmentsClient, DecryptFileError, EncryptFileError}; pub use card::{CardBrand, CardView}; pub use cipher::{ - Cipher, CipherError, CipherListView, CipherListViewType, CipherRepromptType, CipherType, - CipherView, EncryptionContext, + Cipher, CipherError, CipherId, CipherListView, CipherListViewType, CipherRepromptType, + CipherType, CipherView, EncryptionContext, }; pub use cipher_client::CiphersClient; pub use field::FieldView; diff --git a/crates/bitwarden-vault/src/collection.rs b/crates/bitwarden-vault/src/collection.rs index 045cc935d..15651b0ad 100644 --- a/crates/bitwarden-vault/src/collection.rs +++ b/crates/bitwarden-vault/src/collection.rs @@ -1,14 +1,16 @@ use bitwarden_api_api::models::CollectionDetailsResponseModel; use bitwarden_core::{ key_management::{KeyIds, SymmetricKeyId}, - require, + require, OrganizationId, }; use bitwarden_crypto::{CryptoError, Decryptable, EncString, IdentifyKey, KeyStoreContext}; +use bitwarden_uuid::uuid_newtype; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::VaultParseError; +uuid_newtype!(pub CollectionId); + #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] @@ -18,8 +20,8 @@ use crate::VaultParseError; tsify(into_wasm_abi, from_wasm_abi) )] pub struct Collection { - pub id: Option, - pub organization_id: Uuid, + pub id: Option, + pub organization_id: OrganizationId, pub name: EncString, @@ -33,8 +35,8 @@ pub struct Collection { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] pub struct CollectionView { - pub id: Option, - pub organization_id: Uuid, + pub id: Option, + pub organization_id: OrganizationId, pub name: String, @@ -46,7 +48,7 @@ pub struct CollectionView { impl IdentifyKey for Collection { fn key_identifier(&self) -> SymmetricKeyId { - SymmetricKeyId::Organization(self.organization_id) + SymmetricKeyId::Organization(self.organization_id.into()) } } @@ -75,8 +77,8 @@ impl TryFrom for Collection { fn try_from(collection: CollectionDetailsResponseModel) -> Result { Ok(Collection { - id: collection.id, - organization_id: require!(collection.organization_id), + id: collection.id.map(CollectionId::new), + organization_id: OrganizationId::new(require!(collection.organization_id)), name: require!(collection.name).parse()?, external_id: collection.external_id, hide_passwords: collection.hide_passwords.unwrap_or(false), diff --git a/crates/bitwarden-vault/src/folder.rs b/crates/bitwarden-vault/src/folder.rs index d398b986c..7637ed905 100644 --- a/crates/bitwarden-vault/src/folder.rs +++ b/crates/bitwarden-vault/src/folder.rs @@ -6,20 +6,22 @@ use bitwarden_core::{ use bitwarden_crypto::{ CryptoError, Decryptable, EncString, Encryptable, IdentifyKey, KeyStoreContext, }; +use bitwarden_uuid::uuid_newtype; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use uuid::Uuid; #[cfg(feature = "wasm")] use {tsify_next::Tsify, wasm_bindgen::prelude::*}; use crate::VaultParseError; +uuid_newtype!(pub FolderId); + #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct Folder { - id: Option, + id: Option, name: EncString, revision_date: DateTime, } @@ -29,7 +31,7 @@ pub struct Folder { #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct FolderView { - pub id: Option, + pub id: Option, pub name: String, pub revision_date: DateTime, } @@ -78,7 +80,7 @@ impl TryFrom for Folder { fn try_from(folder: FolderResponseModel) -> Result { Ok(Folder { - id: folder.id, + id: folder.id.map(FolderId::new), name: require!(EncString::try_from_optional(folder.name)?), revision_date: require!(folder.revision_date).parse()?, }) diff --git a/crates/bitwarden-vault/src/lib.rs b/crates/bitwarden-vault/src/lib.rs index 15ac70a1b..c9f54fa5e 100644 --- a/crates/bitwarden-vault/src/lib.rs +++ b/crates/bitwarden-vault/src/lib.rs @@ -8,11 +8,11 @@ mod uniffi_support; mod cipher; pub use cipher::*; mod collection; -pub use collection::{Collection, CollectionView}; +pub use collection::{Collection, CollectionId, CollectionView}; mod collection_client; pub use collection_client::CollectionsClient; mod folder; -pub use folder::{Folder, FolderView}; +pub use folder::{Folder, FolderId, FolderView}; mod folder_client; pub use folder_client::FoldersClient; mod password_history; diff --git a/crates/bitwarden-vault/src/sync.rs b/crates/bitwarden-vault/src/sync.rs index d1fd46723..eeb1e9f1c 100644 --- a/crates/bitwarden-vault/src/sync.rs +++ b/crates/bitwarden-vault/src/sync.rs @@ -3,10 +3,10 @@ use bitwarden_api_api::models::{ }; use bitwarden_core::{ client::encryption_settings::EncryptionSettingsError, require, Client, MissingFieldError, + OrganizationId, UserId, }; use serde::{Deserialize, Serialize}; use thiserror::Error; -use uuid::Uuid; use crate::{Cipher, Collection, Folder, GlobalDomains, VaultParseError}; @@ -41,6 +41,7 @@ pub(crate) async fn sync(client: &Client, input: &SyncRequest) -> Result Result Result { Ok(ProfileOrganizationResponse { - id: require!(response.id), + id: OrganizationId::new(require!(response.id)), }) } } @@ -129,7 +130,7 @@ impl ProfileResponse { response: ProfileResponseModel, ) -> Result { Ok(ProfileResponse { - id: require!(response.id), + id: UserId::new(require!(response.id)), name: require!(response.name), email: require!(response.email), //key: response.key, From bfe2792ce5126fe871238348896888e6732a9a92 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 26 May 2025 12:36:41 +0200 Subject: [PATCH 2/8] Update KeyIds to use OrganizationId --- bitwarden_license/bitwarden-sm/src/projects/create.rs | 4 ++-- .../bitwarden-sm/src/projects/project_response.rs | 4 ++-- bitwarden_license/bitwarden-sm/src/projects/update.rs | 4 ++-- bitwarden_license/bitwarden-sm/src/secrets/create.rs | 4 ++-- bitwarden_license/bitwarden-sm/src/secrets/list.rs | 4 ++-- .../bitwarden-sm/src/secrets/secret_response.rs | 4 ++-- bitwarden_license/bitwarden-sm/src/secrets/update.rs | 4 ++-- crates/bitwarden-core/src/client/encryption_settings.rs | 1 - crates/bitwarden-core/src/client/login_method.rs | 3 ++- crates/bitwarden-core/src/key_management/mod.rs | 6 ++++-- crates/bitwarden-uuid-macro/src/lib.rs | 4 ++-- 11 files changed, 22 insertions(+), 20 deletions(-) diff --git a/bitwarden_license/bitwarden-sm/src/projects/create.rs b/bitwarden_license/bitwarden-sm/src/projects/create.rs index e7cb488ac..d61738093 100644 --- a/bitwarden_license/bitwarden-sm/src/projects/create.rs +++ b/bitwarden_license/bitwarden-sm/src/projects/create.rs @@ -1,5 +1,5 @@ use bitwarden_api_api::models::ProjectCreateRequestModel; -use bitwarden_core::{key_management::SymmetricKeyId, Client}; +use bitwarden_core::{key_management::SymmetricKeyId, Client, OrganizationId}; use bitwarden_crypto::Encryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -27,7 +27,7 @@ pub(crate) async fn create_project( input.validate()?; let key_store = client.internal.get_key_store(); - let key = SymmetricKeyId::Organization(input.organization_id); + let key = SymmetricKeyId::Organization(OrganizationId::new(input.organization_id)); let project = Some(ProjectCreateRequestModel { name: input diff --git a/bitwarden_license/bitwarden-sm/src/projects/project_response.rs b/bitwarden_license/bitwarden-sm/src/projects/project_response.rs index adeb1f79f..935f083f0 100644 --- a/bitwarden_license/bitwarden-sm/src/projects/project_response.rs +++ b/bitwarden_license/bitwarden-sm/src/projects/project_response.rs @@ -1,7 +1,7 @@ use bitwarden_api_api::models::ProjectResponseModel; use bitwarden_core::{ key_management::{KeyIds, SymmetricKeyId}, - require, + require, OrganizationId, }; use bitwarden_crypto::{Decryptable, EncString, KeyStoreContext}; use chrono::{DateTime, Utc}; @@ -27,7 +27,7 @@ impl ProjectResponse { ctx: &mut KeyStoreContext, ) -> Result { let organization_id = require!(response.organization_id); - let key = SymmetricKeyId::Organization(organization_id); + let key = SymmetricKeyId::Organization(OrganizationId::new(organization_id)); let name = require!(response.name) .parse::()? diff --git a/bitwarden_license/bitwarden-sm/src/projects/update.rs b/bitwarden_license/bitwarden-sm/src/projects/update.rs index b1da9aade..9ef6c5b8c 100644 --- a/bitwarden_license/bitwarden-sm/src/projects/update.rs +++ b/bitwarden_license/bitwarden-sm/src/projects/update.rs @@ -1,5 +1,5 @@ use bitwarden_api_api::models::ProjectUpdateRequestModel; -use bitwarden_core::{key_management::SymmetricKeyId, Client}; +use bitwarden_core::{key_management::SymmetricKeyId, Client, OrganizationId}; use bitwarden_crypto::Encryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -29,7 +29,7 @@ pub(crate) async fn update_project( input.validate()?; let key_store = client.internal.get_key_store(); - let key = SymmetricKeyId::Organization(input.organization_id); + let key = SymmetricKeyId::Organization(OrganizationId::new(input.organization_id)); let project = Some(ProjectUpdateRequestModel { name: input diff --git a/bitwarden_license/bitwarden-sm/src/secrets/create.rs b/bitwarden_license/bitwarden-sm/src/secrets/create.rs index bd3c96215..03dcd9add 100644 --- a/bitwarden_license/bitwarden-sm/src/secrets/create.rs +++ b/bitwarden_license/bitwarden-sm/src/secrets/create.rs @@ -1,5 +1,5 @@ use bitwarden_api_api::models::SecretCreateRequestModel; -use bitwarden_core::{key_management::SymmetricKeyId, Client}; +use bitwarden_core::{key_management::SymmetricKeyId, Client, OrganizationId}; use bitwarden_crypto::Encryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -35,7 +35,7 @@ pub(crate) async fn create_secret( input.validate()?; let key_store = client.internal.get_key_store(); - let key = SymmetricKeyId::Organization(input.organization_id); + let key = SymmetricKeyId::Organization(OrganizationId::new(input.organization_id)); let secret = { let mut ctx = key_store.context(); diff --git a/bitwarden_license/bitwarden-sm/src/secrets/list.rs b/bitwarden_license/bitwarden-sm/src/secrets/list.rs index 25e8aea32..0ea2e07c5 100644 --- a/bitwarden_license/bitwarden-sm/src/secrets/list.rs +++ b/bitwarden_license/bitwarden-sm/src/secrets/list.rs @@ -4,7 +4,7 @@ use bitwarden_api_api::models::{ use bitwarden_core::{ client::Client, key_management::{KeyIds, SymmetricKeyId}, - require, + require, OrganizationId, }; use bitwarden_crypto::{Decryptable, EncString, KeyStoreContext}; use schemars::JsonSchema; @@ -96,7 +96,7 @@ impl SecretIdentifierResponse { ctx: &mut KeyStoreContext, ) -> Result { let organization_id = require!(response.organization_id); - let enc_key = SymmetricKeyId::Organization(organization_id); + let enc_key = SymmetricKeyId::Organization(OrganizationId::new(organization_id)); let key = require!(response.key) .parse::()? diff --git a/bitwarden_license/bitwarden-sm/src/secrets/secret_response.rs b/bitwarden_license/bitwarden-sm/src/secrets/secret_response.rs index ce3c28f4b..f16e494b3 100644 --- a/bitwarden_license/bitwarden-sm/src/secrets/secret_response.rs +++ b/bitwarden_license/bitwarden-sm/src/secrets/secret_response.rs @@ -3,7 +3,7 @@ use bitwarden_api_api::models::{ }; use bitwarden_core::{ key_management::{KeyIds, SymmetricKeyId}, - require, + require, OrganizationId, }; use bitwarden_crypto::{Decryptable, EncString, KeyStoreContext}; use chrono::{DateTime, Utc}; @@ -51,7 +51,7 @@ impl SecretResponse { ctx: &mut KeyStoreContext, ) -> Result { let organization_id = require!(response.organization_id); - let enc_key = SymmetricKeyId::Organization(organization_id); + let enc_key = SymmetricKeyId::Organization(OrganizationId::new(organization_id)); let key = require!(response.key) .parse::()? diff --git a/bitwarden_license/bitwarden-sm/src/secrets/update.rs b/bitwarden_license/bitwarden-sm/src/secrets/update.rs index 462320d62..fae7acb30 100644 --- a/bitwarden_license/bitwarden-sm/src/secrets/update.rs +++ b/bitwarden_license/bitwarden-sm/src/secrets/update.rs @@ -1,5 +1,5 @@ use bitwarden_api_api::models::SecretUpdateRequestModel; -use bitwarden_core::{key_management::SymmetricKeyId, Client}; +use bitwarden_core::{key_management::SymmetricKeyId, Client, OrganizationId}; use bitwarden_crypto::Encryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -34,7 +34,7 @@ pub(crate) async fn update_secret( input.validate()?; let key_store = client.internal.get_key_store(); - let key = SymmetricKeyId::Organization(input.organization_id); + let key = SymmetricKeyId::Organization(OrganizationId::new(input.organization_id)); let secret = { let mut ctx = key_store.context(); diff --git a/crates/bitwarden-core/src/client/encryption_settings.rs b/crates/bitwarden-core/src/client/encryption_settings.rs index 9a4baf596..792f6d945 100644 --- a/crates/bitwarden-core/src/client/encryption_settings.rs +++ b/crates/bitwarden-core/src/client/encryption_settings.rs @@ -6,7 +6,6 @@ use thiserror::Error; #[cfg(any(feature = "secrets", feature = "internal"))] use crate::OrganizationId; - use crate::{ error::UserIdAlreadySetError, key_management::{AsymmetricKeyId, KeyIds, SymmetricKeyId}, diff --git a/crates/bitwarden-core/src/client/login_method.rs b/crates/bitwarden-core/src/client/login_method.rs index 84f64a653..a1b78a4ea 100644 --- a/crates/bitwarden-core/src/client/login_method.rs +++ b/crates/bitwarden-core/src/client/login_method.rs @@ -1,10 +1,11 @@ #[cfg(feature = "secrets")] use std::path::PathBuf; +use bitwarden_crypto::Kdf; + #[cfg(feature = "secrets")] use crate::auth::AccessToken; use crate::OrganizationId; -use bitwarden_crypto::Kdf; #[derive(Debug)] pub(crate) enum LoginMethod { diff --git a/crates/bitwarden-core/src/key_management/mod.rs b/crates/bitwarden-core/src/key_management/mod.rs index dd13ab21c..dfc7c12df 100644 --- a/crates/bitwarden-core/src/key_management/mod.rs +++ b/crates/bitwarden-core/src/key_management/mod.rs @@ -9,12 +9,14 @@ //! [Encryptable](bitwarden_crypto::Encryptable) and [Decryptable](bitwarden_crypto::Encryptable). use bitwarden_crypto::{key_ids, KeyStore, SymmetricCryptoKey}; +use crate::OrganizationId; + key_ids! { #[symmetric] pub enum SymmetricKeyId { Master, User, - Organization(uuid::Uuid), + Organization(OrganizationId), #[local] Local(&'static str), } @@ -50,7 +52,7 @@ pub fn create_test_crypto_with_user_key(key: SymmetricCryptoKey) -> KeyStore KeyStore { let store = KeyStore::default(); diff --git a/crates/bitwarden-uuid-macro/src/lib.rs b/crates/bitwarden-uuid-macro/src/lib.rs index 63dc108e3..52fc99ab4 100644 --- a/crates/bitwarden-uuid-macro/src/lib.rs +++ b/crates/bitwarden-uuid-macro/src/lib.rs @@ -23,8 +23,8 @@ pub fn uuid_newtype(input: TokenStream) -> TokenStream { #[cfg_attr(feature = "wasm", derive(::tsify_next::Tsify), tsify(into_wasm_abi, from_wasm_abi))] #[derive( ::serde::Serialize, ::serde::Deserialize, - ::std::cmp::PartialEq, ::std::cmp::Eq, ::std::hash::Hash, - ::std::clone::Clone, ::std::marker::Copy, ::std::fmt::Debug + ::std::cmp::PartialEq, ::std::cmp::Eq, ::std::cmp::PartialOrd, ::std::cmp::Ord, + ::std::hash::Hash, ::std::clone::Clone, ::std::marker::Copy, ::std::fmt::Debug )] #[repr(transparent)] #vis struct #ident From cb143270f5cfa3933a166f61a4e5dcee6453e079 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 26 May 2025 12:46:59 +0200 Subject: [PATCH 3/8] Resolve clippy --- .../src/auth/login/access_token.rs | 2 +- .../src/client/encryption_settings.rs | 4 ++-- crates/bitwarden-core/src/client/internal.rs | 10 ++------- crates/bitwarden-vault/src/cipher/cipher.rs | 22 +++++++++---------- crates/bitwarden-vault/src/collection.rs | 2 +- 5 files changed, 17 insertions(+), 23 deletions(-) diff --git a/crates/bitwarden-core/src/auth/login/access_token.rs b/crates/bitwarden-core/src/auth/login/access_token.rs index c0596e7cb..f324a52de 100644 --- a/crates/bitwarden-core/src/auth/login/access_token.rs +++ b/crates/bitwarden-core/src/auth/login/access_token.rs @@ -35,7 +35,7 @@ pub(crate) async fn login_access_token( .set_login_method(LoginMethod::ServiceAccount( ServiceAccountLoginMethod::AccessToken { access_token, - organization_id: organization_id.into(), + organization_id: organization_id, state_file: Some(state_file.to_path_buf()), }, )); diff --git a/crates/bitwarden-core/src/client/encryption_settings.rs b/crates/bitwarden-core/src/client/encryption_settings.rs index 792f6d945..a30a9085e 100644 --- a/crates/bitwarden-core/src/client/encryption_settings.rs +++ b/crates/bitwarden-core/src/client/encryption_settings.rs @@ -94,7 +94,7 @@ impl EncryptionSettings { #[allow(deprecated)] store .context_mut() - .set_symmetric_key(SymmetricKeyId::Organization(organization_id.into()), key) + .set_symmetric_key(SymmetricKeyId::Organization(organization_id), key) .expect("Mutable context"); } @@ -122,7 +122,7 @@ impl EncryptionSettings { for (org_id, org_enc_key) in org_enc_keys { ctx.decapsulate_key_unsigned( AsymmetricKeyId::UserPrivateKey, - SymmetricKeyId::Organization(org_id.into()), + SymmetricKeyId::Organization(org_id), &org_enc_key, )?; } diff --git a/crates/bitwarden-core/src/client/internal.rs b/crates/bitwarden-core/src/client/internal.rs index 65f3ad982..1654e30d5 100644 --- a/crates/bitwarden-core/src/client/internal.rs +++ b/crates/bitwarden-core/src/client/internal.rs @@ -223,7 +223,7 @@ impl InternalClient { organization_id: OrganizationId, key: SymmetricCryptoKey, ) { - EncryptionSettings::new_single_org_key(organization_id.into(), key, &self.key_store); + EncryptionSettings::new_single_org_key(organization_id, key, &self.key_store); } #[cfg(feature = "internal")] @@ -231,12 +231,6 @@ impl InternalClient { &self, org_keys: Vec<(OrganizationId, UnsignedSharedKey)>, ) -> Result<(), EncryptionSettingsError> { - EncryptionSettings::set_org_keys( - org_keys - .into_iter() - .map(|(id, key)| (id.into(), key)) - .collect(), - &self.key_store, - ) + EncryptionSettings::set_org_keys(org_keys, &self.key_store) } } diff --git a/crates/bitwarden-vault/src/cipher/cipher.rs b/crates/bitwarden-vault/src/cipher/cipher.rs index c5c0ff992..98c7a98d3 100644 --- a/crates/bitwarden-vault/src/cipher/cipher.rs +++ b/crates/bitwarden-vault/src/cipher/cipher.rs @@ -548,7 +548,7 @@ impl CipherView { organization_id: OrganizationId, ) -> Result<(), CipherError> { let old_key = self.key_identifier(); - let new_key = SymmetricKeyId::Organization(organization_id.into()); + let new_key = SymmetricKeyId::Organization(organization_id); // If any attachment is missing a key we can't reencrypt the attachment keys if self.attachments.iter().flatten().any(|a| a.key.is_none()) { @@ -660,7 +660,7 @@ impl Decryptable for Cipher { impl IdentifyKey for Cipher { fn key_identifier(&self) -> SymmetricKeyId { match self.organization_id { - Some(organization_id) => SymmetricKeyId::Organization(organization_id.into()), + Some(organization_id) => SymmetricKeyId::Organization(organization_id), None => SymmetricKeyId::User, } } @@ -669,7 +669,7 @@ impl IdentifyKey for Cipher { impl IdentifyKey for CipherView { fn key_identifier(&self) -> SymmetricKeyId { match self.organization_id { - Some(organization_id) => SymmetricKeyId::Organization(organization_id.into()), + Some(organization_id) => SymmetricKeyId::Organization(organization_id), None => SymmetricKeyId::User, } } @@ -678,7 +678,7 @@ impl IdentifyKey for CipherView { impl IdentifyKey for CipherListView { fn key_identifier(&self) -> SymmetricKeyId { match self.organization_id { - Some(organization_id) => SymmetricKeyId::Organization(organization_id.into()), + Some(organization_id) => SymmetricKeyId::Organization(organization_id), None => SymmetricKeyId::User, } } @@ -996,7 +996,7 @@ mod tests { let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); + let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); // Create a cipher with a user key let mut cipher = generate_cipher(); @@ -1021,7 +1021,7 @@ mod tests { let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); + let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); // Create a cipher with a user key let mut cipher = generate_cipher(); @@ -1041,7 +1041,7 @@ mod tests { let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); + let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); let mut cipher = generate_cipher(); let attachment = AttachmentView { @@ -1065,8 +1065,8 @@ mod tests { let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); - let org_key = SymmetricKeyId::Organization(org.into()); + let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); + let org_key = SymmetricKeyId::Organization(org); // Attachment has a key that is encrypted with the user key, as the cipher has no key itself let (attachment_key_enc, attachment_key_val) = { @@ -1133,8 +1133,8 @@ mod tests { let org = OrganizationId::new_v4(); let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let org_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); - let key_store = create_test_crypto_with_user_and_org_key(key, org.into(), org_key); - let org_key = SymmetricKeyId::Organization(org.into()); + let key_store = create_test_crypto_with_user_and_org_key(key, org, org_key); + let org_key = SymmetricKeyId::Organization(org); let mut ctx = key_store.context(); diff --git a/crates/bitwarden-vault/src/collection.rs b/crates/bitwarden-vault/src/collection.rs index 15651b0ad..b2f0cbc4d 100644 --- a/crates/bitwarden-vault/src/collection.rs +++ b/crates/bitwarden-vault/src/collection.rs @@ -48,7 +48,7 @@ pub struct CollectionView { impl IdentifyKey for Collection { fn key_identifier(&self) -> SymmetricKeyId { - SymmetricKeyId::Organization(self.organization_id.into()) + SymmetricKeyId::Organization(self.organization_id) } } From ed060757c2cfdd0a5538b4b2e8681022501bd839 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 26 May 2025 12:48:35 +0200 Subject: [PATCH 4/8] Sort --- crates/bitwarden-vault/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-vault/Cargo.toml b/crates/bitwarden-vault/Cargo.toml index 1f582ceb0..ebceec391 100644 --- a/crates/bitwarden-vault/Cargo.toml +++ b/crates/bitwarden-vault/Cargo.toml @@ -18,7 +18,7 @@ keywords.workspace = true uniffi = [ "bitwarden-core/uniffi", "bitwarden-crypto/uniffi", - "dep:uniffi", + "dep:uniffi" ] # Uniffi bindings wasm = ["dep:tsify-next", "dep:wasm-bindgen"] # WASM support From 38855704e84451ea3b48ab6628e7609469f59baf Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 26 May 2025 13:01:40 +0200 Subject: [PATCH 5/8] Clippy --- crates/bitwarden-core/src/auth/login/access_token.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-core/src/auth/login/access_token.rs b/crates/bitwarden-core/src/auth/login/access_token.rs index f324a52de..c25863605 100644 --- a/crates/bitwarden-core/src/auth/login/access_token.rs +++ b/crates/bitwarden-core/src/auth/login/access_token.rs @@ -35,7 +35,7 @@ pub(crate) async fn login_access_token( .set_login_method(LoginMethod::ServiceAccount( ServiceAccountLoginMethod::AccessToken { access_token, - organization_id: organization_id, + organization_id, state_file: Some(state_file.to_path_buf()), }, )); From 0b2df1fc637b2b43f8441b9ec01f52d9f4e8832d Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 26 May 2025 13:04:35 +0200 Subject: [PATCH 6/8] Resolve unused import --- crates/bitwarden-core/src/client/login_method.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bitwarden-core/src/client/login_method.rs b/crates/bitwarden-core/src/client/login_method.rs index a1b78a4ea..f412976fa 100644 --- a/crates/bitwarden-core/src/client/login_method.rs +++ b/crates/bitwarden-core/src/client/login_method.rs @@ -4,8 +4,7 @@ use std::path::PathBuf; use bitwarden_crypto::Kdf; #[cfg(feature = "secrets")] -use crate::auth::AccessToken; -use crate::OrganizationId; +use crate::{auth::AccessToken, OrganizationId}; #[derive(Debug)] pub(crate) enum LoginMethod { From 2417bf6354285d47c067539e546f6d3037195979 Mon Sep 17 00:00:00 2001 From: Hinton Date: Tue, 10 Jun 2025 13:48:22 +0200 Subject: [PATCH 7/8] Fix compile --- crates/bitwarden-core/src/client/internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-core/src/client/internal.rs b/crates/bitwarden-core/src/client/internal.rs index 2bf5e5c6c..17214559a 100644 --- a/crates/bitwarden-core/src/client/internal.rs +++ b/crates/bitwarden-core/src/client/internal.rs @@ -184,7 +184,7 @@ impl InternalClient { } #[allow(missing_docs)] - pub fn init_user_id(&self, user_id: Uuid) -> Result<(), UserIdAlreadySetError> { + pub fn init_user_id(&self, user_id: UserId) -> Result<(), UserIdAlreadySetError> { self.user_id.set(user_id).map_err(|_| UserIdAlreadySetError) } From 14da1d8f06042cacb5c6d703df6942d73e9c69b6 Mon Sep 17 00:00:00 2001 From: Hinton Date: Tue, 10 Jun 2025 14:48:58 +0200 Subject: [PATCH 8/8] Remove old uuid --- crates/bitwarden-wasm-internal/src/custom_types.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bitwarden-wasm-internal/src/custom_types.rs b/crates/bitwarden-wasm-internal/src/custom_types.rs index f910d1173..cae9ead52 100644 --- a/crates/bitwarden-wasm-internal/src/custom_types.rs +++ b/crates/bitwarden-wasm-internal/src/custom_types.rs @@ -10,10 +10,7 @@ import { Tagged } from "type-fest"; * * Never create or cast to this type directly, use the `uuid()` function instead. */ -// TODO: Uncomment this when the `uuid` crate is used. -// export type Uuid = unknown; - -export type Uuid = string; +export type Uuid = unknown; /** * RFC3339 compliant date-time string.