From b38e90827636b76699c562db7a77a4b9f41213b8 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 18 Dec 2025 17:59:32 +0100 Subject: [PATCH 1/4] Rename asymmetric key to private key --- .../bitwarden-core/src/auth/auth_request.rs | 15 +- crates/bitwarden-core/src/auth/tde.rs | 5 +- .../src/client/encryption_settings.rs | 6 +- .../account_cryptographic_state.rs | 22 +-- .../src/key_management/crypto.rs | 31 ++-- .../bitwarden-core/src/key_management/mod.rs | 6 +- .../src/platform/generate_fingerprint.rs | 4 +- .../src/enc_string/asymmetric.rs | 16 +- .../bitwarden-crypto/src/keys/device_key.rs | 7 +- crates/bitwarden-crypto/src/keys/mod.rs | 8 +- ...crypto_key.rs => public_key_encryption.rs} | 37 +++-- .../src/keys/rotateable_key_set.rs | 13 +- .../src/keys/signed_public_key.rs | 21 ++- crates/bitwarden-crypto/src/store/context.rs | 151 +++++++----------- .../src/store/key_rotation.rs | 11 +- crates/bitwarden-crypto/src/store/mod.rs | 10 +- .../src/traits/encryptable.rs | 4 +- crates/bitwarden-crypto/src/traits/key_id.rs | 22 +-- .../src/pure_crypto.rs | 29 ++-- crates/memory-testing/src/main.rs | 2 +- 20 files changed, 187 insertions(+), 233 deletions(-) rename crates/bitwarden-crypto/src/keys/{asymmetric_crypto_key.rs => public_key_encryption.rs} (92%) diff --git a/crates/bitwarden-core/src/auth/auth_request.rs b/crates/bitwarden-core/src/auth/auth_request.rs index 7a16068f7..e6d9fcffa 100644 --- a/crates/bitwarden-core/src/auth/auth_request.rs +++ b/crates/bitwarden-core/src/auth/auth_request.rs @@ -1,6 +1,6 @@ use bitwarden_crypto::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, CryptoError, PublicKeyEncryptionAlgorithm, - SpkiPublicKeyBytes, UnsignedSharedKey, fingerprint, generate_random_alphanumeric, + CryptoError, PrivateKey, PublicKey, PublicKeyEncryptionAlgorithm, SpkiPublicKeyBytes, + UnsignedSharedKey, fingerprint, generate_random_alphanumeric, }; #[cfg(feature = "internal")] use bitwarden_crypto::{EncString, SymmetricCryptoKey}; @@ -32,7 +32,7 @@ pub struct AuthRequestResponse { /// to another device. Where the user confirms the validity by confirming the fingerprint. The user /// key is then encrypted using the public key and returned to the initiating device. pub(crate) fn new_auth_request(email: &str) -> Result { - let key = AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); + let key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); let spki = key.to_public_key().to_der()?; @@ -52,7 +52,7 @@ pub(crate) fn auth_request_decrypt_user_key( private_key: B64, user_key: UnsignedSharedKey, ) -> Result { - let key = AsymmetricCryptoKey::from_der(&private_key.as_bytes().into())?; + let key = PrivateKey::from_der(&private_key.as_bytes().into())?; let key: SymmetricCryptoKey = user_key.decapsulate_key_unsigned(&key)?; Ok(key) } @@ -66,7 +66,7 @@ pub(crate) fn auth_request_decrypt_master_key( ) -> Result { use bitwarden_crypto::MasterKey; - let key = AsymmetricCryptoKey::from_der(&private_key.as_bytes().into())?; + let key = PrivateKey::from_der(&private_key.as_bytes().into())?; let master_key: SymmetricCryptoKey = master_key.decapsulate_key_unsigned(&key)?; let master_key = MasterKey::try_from(&master_key)?; @@ -88,7 +88,7 @@ pub(crate) fn approve_auth_request( client: &Client, public_key: B64, ) -> Result { - let public_key = AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from(&public_key))?; + let public_key = PublicKey::from_der(&SpkiPublicKeyBytes::from(&public_key))?; let key_store = client.internal.get_key_store(); let ctx = key_store.context(); @@ -130,8 +130,7 @@ mod tests { 248, 43, 255, 67, 35, 61, 245, 93, ]; - let private_key = - AsymmetricCryptoKey::from_der(&request.private_key.as_bytes().into()).unwrap(); + let private_key = PrivateKey::from_der(&request.private_key.as_bytes().into()).unwrap(); let secret = BitwardenLegacyKeyBytes::from(secret); let encrypted = UnsignedSharedKey::encapsulate_key_unsigned( diff --git a/crates/bitwarden-core/src/auth/tde.rs b/crates/bitwarden-core/src/auth/tde.rs index e913b3245..8ae021aa6 100644 --- a/crates/bitwarden-core/src/auth/tde.rs +++ b/crates/bitwarden-core/src/auth/tde.rs @@ -1,5 +1,5 @@ use bitwarden_crypto::{ - AsymmetricPublicCryptoKey, DeviceKey, EncString, Kdf, SpkiPublicKeyBytes, SymmetricCryptoKey, + DeviceKey, EncString, Kdf, PublicKey, SpkiPublicKeyBytes, SymmetricCryptoKey, TrustDeviceResponse, UnsignedSharedKey, UserKey, }; use bitwarden_encoding::B64; @@ -18,8 +18,7 @@ pub(super) fn make_register_tde_keys( org_public_key: B64, remember_device: bool, ) -> Result { - let public_key = - AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from(&org_public_key))?; + let public_key = PublicKey::from_der(&SpkiPublicKeyBytes::from(&org_public_key))?; let user_key = UserKey::new(SymmetricCryptoKey::make_aes256_cbc_hmac_key()); let key_pair = user_key.make_key_pair()?; diff --git a/crates/bitwarden-core/src/client/encryption_settings.rs b/crates/bitwarden-core/src/client/encryption_settings.rs index 826cdbf76..fcc378405 100644 --- a/crates/bitwarden-core/src/client/encryption_settings.rs +++ b/crates/bitwarden-core/src/client/encryption_settings.rs @@ -61,7 +61,7 @@ impl EncryptionSettings { org_enc_keys: Vec<(OrganizationId, UnsignedSharedKey)>, store: &KeyStore, ) -> Result<(), EncryptionSettingsError> { - use crate::key_management::AsymmetricKeyId; + use crate::key_management::PrivateKeyId; let mut ctx = store.context_mut(); @@ -70,7 +70,7 @@ impl EncryptionSettings { return Ok(()); } - if !ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey) { + if !ctx.has_private_key(PrivateKeyId::UserPrivateKey) { return Err(MissingPrivateKeyError.into()); } @@ -81,7 +81,7 @@ impl EncryptionSettings { // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { ctx.decapsulate_key_unsigned( - AsymmetricKeyId::UserPrivateKey, + PrivateKeyId::UserPrivateKey, SymmetricKeyId::Organization(org_id), &org_enc_key, )?; diff --git a/crates/bitwarden-core/src/key_management/account_cryptographic_state.rs b/crates/bitwarden-core/src/key_management/account_cryptographic_state.rs index fd058d5aa..bebbe81a6 100644 --- a/crates/bitwarden-core/src/key_management/account_cryptographic_state.rs +++ b/crates/bitwarden-core/src/key_management/account_cryptographic_state.rs @@ -12,7 +12,7 @@ use std::sync::RwLock; use bitwarden_api_api::models::{AccountKeysRequestModel, SecurityStateModel}; use bitwarden_crypto::{ - AsymmetricPublicCryptoKey, CoseSerializable, CryptoError, EncString, KeyStore, KeyStoreContext, + CoseSerializable, CryptoError, EncString, KeyStore, KeyStoreContext, PublicKey, PublicKeyEncryptionAlgorithm, SignatureAlgorithm, SignedPublicKey, SymmetricKeyAlgorithm, VerifyingKey, }; @@ -27,7 +27,7 @@ use tsify::Tsify; use crate::{ UserId, key_management::{ - AsymmetricKeyId, KeyIds, SecurityState, SignedSecurityState, SigningKeyId, SymmetricKeyId, + KeyIds, PrivateKeyId, SecurityState, SignedSecurityState, SigningKeyId, SymmetricKeyId, }, }; @@ -214,7 +214,7 @@ impl WrappedAccountCryptographicState { mut ctx: KeyStoreContext, ) -> Result<(), AccountCryptographyInitializationError> { if ctx.has_symmetric_key(SymmetricKeyId::User) - || ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey) + || ctx.has_private_key(PrivateKeyId::UserPrivateKey) || ctx.has_signing_key(SigningKeyId::UserSigningKey) { return Err(AccountCryptographyInitializationError::KeyStoreAlreadyInitialized); @@ -232,7 +232,7 @@ impl WrappedAccountCryptographicState { // Some users have unreadable V1 private keys. In this case, we set no keys to // state. if let Ok(private_key_id) = ctx.unwrap_private_key(user_key, private_key) { - ctx.persist_asymmetric_key(private_key_id, AsymmetricKeyId::UserPrivateKey)?; + ctx.persist_private_key(private_key_id, PrivateKeyId::UserPrivateKey)?; } else { tracing::warn!( "V1 private key could not be unwrapped, skipping setting private key" @@ -272,7 +272,7 @@ impl WrappedAccountCryptographicState { .to_owned() .verify_and_unwrap(&ctx.get_verifying_key(signing_key_id)?) .map_err(|_| AccountCryptographyInitializationError::TamperedData)?; - ctx.persist_asymmetric_key(private_key_id, AsymmetricKeyId::UserPrivateKey)?; + ctx.persist_private_key(private_key_id, PrivateKeyId::UserPrivateKey)?; ctx.persist_signing_key(signing_key_id, SigningKeyId::UserSigningKey)?; ctx.persist_symmetric_key(user_key, SymmetricKeyId::User)?; // Not manually dropping ctx here would lead to a deadlock, since storing the state @@ -311,7 +311,7 @@ impl WrappedAccountCryptographicState { fn public_key( &self, store: &KeyStore, - ) -> Result, AccountCryptographyInitializationError> { + ) -> Result, AccountCryptographyInitializationError> { match self { WrappedAccountCryptographicState::V1 { private_key } | WrappedAccountCryptographicState::V2 { private_key, .. } => { @@ -346,7 +346,7 @@ mod tests { use bitwarden_crypto::{KeyStore, PrimitiveEncryptable}; use super::*; - use crate::key_management::{AsymmetricKeyId, SigningKeyId, SymmetricKeyId}; + use crate::key_management::{PrivateKeyId, SigningKeyId, SymmetricKeyId}; #[test] fn test_set_to_context_v1() { @@ -388,7 +388,7 @@ mod tests { let ctx = store.context(); // Assert that the private key and user symmetric key were set in the store - assert!(ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey)); + assert!(ctx.has_private_key(PrivateKeyId::UserPrivateKey)); assert!(ctx.has_symmetric_key(SymmetricKeyId::User)); } @@ -450,7 +450,7 @@ mod tests { assert!( store .context() - .has_asymmetric_key(AsymmetricKeyId::UserPrivateKey) + .has_private_key(PrivateKeyId::UserPrivateKey) ); assert!( store @@ -495,7 +495,7 @@ mod tests { assert_eq!( pk_pair.public_key.unwrap(), B64::from( - ctx.get_public_key(AsymmetricKeyId::UserPrivateKey) + ctx.get_public_key(PrivateKeyId::UserPrivateKey) .unwrap() .to_der() .unwrap() @@ -558,6 +558,6 @@ mod tests { // The user symmetric key should be set assert!(ctx.has_symmetric_key(SymmetricKeyId::User)); // But the private key should NOT be set (due to corruption) - assert!(!ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey)); + assert!(!ctx.has_private_key(PrivateKeyId::UserPrivateKey)); } } diff --git a/crates/bitwarden-core/src/key_management/crypto.rs b/crates/bitwarden-core/src/key_management/crypto.rs index 040668b2f..ba6e0648c 100644 --- a/crates/bitwarden-core/src/key_management/crypto.rs +++ b/crates/bitwarden-core/src/key_management/crypto.rs @@ -7,11 +7,10 @@ use std::collections::HashMap; use bitwarden_crypto::{ - AsymmetricCryptoKey, CoseSerializable, CryptoError, EncString, Kdf, KeyDecryptable, - KeyEncryptable, MasterKey, Pkcs8PrivateKeyBytes, PrimitiveEncryptable, RotateableKeySet, - SignatureAlgorithm, SignedPublicKey, SigningKey, SpkiPublicKeyBytes, SymmetricCryptoKey, - UnsignedSharedKey, UserKey, dangerous_get_v2_rotated_account_keys, - derive_symmetric_key_from_prf, + CoseSerializable, CryptoError, EncString, Kdf, KeyDecryptable, KeyEncryptable, MasterKey, + Pkcs8PrivateKeyBytes, PrimitiveEncryptable, PrivateKey, RotateableKeySet, SignatureAlgorithm, + SignedPublicKey, SigningKey, SpkiPublicKeyBytes, SymmetricCryptoKey, UnsignedSharedKey, + UserKey, dangerous_get_v2_rotated_account_keys, derive_symmetric_key_from_prf, safe::{PasswordProtectedKeyEnvelope, PasswordProtectedKeyEnvelopeError}, }; use bitwarden_encoding::B64; @@ -27,7 +26,7 @@ use crate::{ client::{LoginMethod, UserLoginMethod, encryption_settings::EncryptionSettingsError}, error::StatefulCryptoError, key_management::{ - AsymmetricKeyId, SecurityState, SignedSecurityState, SigningKeyId, SymmetricKeyId, + PrivateKeyId, SecurityState, SignedSecurityState, SigningKeyId, SymmetricKeyId, account_cryptographic_state::WrappedAccountCryptographicState, master_password::{MasterPasswordAuthenticationData, MasterPasswordUnlockData}, }, @@ -543,9 +542,9 @@ pub(super) fn enroll_admin_password_reset( client: &Client, public_key: B64, ) -> Result { - use bitwarden_crypto::AsymmetricPublicCryptoKey; + use bitwarden_crypto::PublicKey; - let public_key = AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from(&public_key))?; + let public_key = PublicKey::from_der(&SpkiPublicKeyBytes::from(&public_key))?; let key_store = client.internal.get_key_store(); let ctx = key_store.context(); // FIXME: [PM-18110] This should be removed once the key store can handle public key encryption @@ -670,8 +669,8 @@ pub(super) fn verify_asymmetric_keys( .map_err(VerifyError::DecryptFailed)?; let decrypted_private_key = Pkcs8PrivateKeyBytes::from(decrypted_private_key); - let private_key = AsymmetricCryptoKey::from_der(&decrypted_private_key) - .map_err(VerifyError::ParseFailed)?; + let private_key = + PrivateKey::from_der(&decrypted_private_key).map_err(VerifyError::ParseFailed)?; let derived_public_key_vec = private_key .to_public_key() @@ -741,7 +740,7 @@ pub(crate) fn make_v2_keys_for_v1_user( let mut ctx = key_store.context(); // Re-use existing private key - let private_key_id = AsymmetricKeyId::UserPrivateKey; + let private_key_id = PrivateKeyId::UserPrivateKey; // Ensure that the function is only called for a V1 user. if client.internal.get_security_version() != 1 { @@ -754,14 +753,14 @@ pub(crate) fn make_v2_keys_for_v1_user( // Ensure the user has a private key. // V1 user must have a private key to upgrade. This should be ensured by the client before // calling the upgrade function. - if !ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey) { + if !ctx.has_private_key(PrivateKeyId::UserPrivateKey) { return Err(StatefulCryptoError::Crypto(CryptoError::MissingKeyId( "UserPrivateKey".to_string(), ))); } #[allow(deprecated)] - let private_key = ctx.dangerous_get_asymmetric_key(private_key_id)?.clone(); + let private_key = ctx.dangerous_get_private_key(private_key_id)?.clone(); // New user key let user_key = SymmetricCryptoKey::make_xchacha20_poly1305_key(); @@ -828,7 +827,7 @@ pub(crate) fn get_v2_rotated_account_keys( .ok_or(StatefulCryptoError::MissingSecurityState)?; let rotated_keys = dangerous_get_v2_rotated_account_keys( - AsymmetricKeyId::UserPrivateKey, + PrivateKeyId::UserPrivateKey, SigningKeyId::UserSigningKey, &ctx, )?; @@ -1248,7 +1247,7 @@ mod tests { let private_key: B64 = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLtEUdxfcLxDj84yaGFsVF5hZ8Hjlb08NMQDy1RnBma06I3ZESshLYzVz4r/gegMn9OOltfV/Yxlyvida8oW6qdlfJ7AVz6Oa8pV7BiL40C7b76+oqraQpyYw2HChANB1AhXL9SqWngKmLZwjA7qiCrmcc0kZHeOb4KnKtp9iVvPVs+8veFvKgYO4ba2AAOHKFdR0W55/agXfAy+fWUAkC8mc9ikyJdQWaPV6OZvC2XFkOseBQm9Rynudh3BQpoWiL6w620efe7t5k+02/EyOFJL9f/XEEjM/+Yo0t3LAfkuhHGeKiRST59Xc9hTEmyJTeVXROtz+0fjqOp3xkaObAgMBAAECggEACs4xhnO0HaZhh1/iH7zORMIRXKeyxP2LQiTR8xwN5JJ9wRWmGAR9VasS7EZFTDidIGVME2u/h4s5EqXnhxfO+0gGksVvgNXJ/qw87E8K2216g6ZNo6vSGA7H1GH2voWwejJ4/k/cJug6dz2S402rRAKh2Wong1arYHSkVlQp3diiMa5FHAOSE+Cy09O2ZsaF9IXQYUtlW6AVXFrBEPYH2kvkaPXchh8VETMijo6tbvoKLnUHe+wTaDMls7hy8exjtVyI59r3DNzjy1lNGaGb5QSnFMXR+eHhPZc844Wv02MxC15zKABADrl58gpJyjTl6XpDdHCYGsmGpVGH3X9TQQKBgQDz/9beFjzq59ve6rGwn+EtnQfSsyYT+jr7GN8lNEXb3YOFXBgPhfFIcHRh2R00Vm9w2ApfAx2cd8xm2I6HuvQ1Os7g26LWazvuWY0Qzb+KaCLQTEGH1RnTq6CCG+BTRq/a3J8M4t38GV5TWlzv8wr9U4dl6FR4efjb65HXs1GQ4QKBgQC7/uHfrOTEHrLeIeqEuSl0vWNqEotFKdKLV6xpOvNuxDGbgW4/r/zaxDqt0YBOXmRbQYSEhmO3oy9J6XfE1SUln0gbavZeW0HESCAmUIC88bDnspUwS9RxauqT5aF8ODKN/bNCWCnBM1xyonPOs1oT1nyparJVdQoG//Y7vkB3+wKBgBqLqPq8fKAp3XfhHLfUjREDVoiLyQa/YI9U42IOz9LdxKNLo6p8rgVthpvmnRDGnpUuS+KOWjhdqDVANjF6G3t3DG7WNl8Rh5Gk2H4NhFswfSkgQrjebFLlBy9gjQVCWXt8KSmjvPbiY6q52Aaa8IUjA0YJAregvXxfopxO+/7BAoGARicvEtDp7WWnSc1OPoj6N14VIxgYcI7SyrzE0d/1x3ffKzB5e7qomNpxKzvqrVP8DzG7ydh8jaKPmv1MfF8tpYRy3AhmN3/GYwCnPqT75YYrhcrWcVdax5gmQVqHkFtIQkRSCIftzPLlpMGKha/YBV8c1fvC4LD0NPh/Ynv0gtECgYEAyOZg95/kte0jpgUEgwuMrzkhY/AaUJULFuR5MkyvReEbtSBQwV5tx60+T95PHNiFooWWVXiLMsAgyI2IbkxVR1Pzdri3gWK5CTfqb7kLuaj/B7SGvBa2Sxo478KS5K8tBBBWkITqo+wLC0mn3uZi1dyMWO1zopTA+KtEGF2dtGQ=".parse().unwrap(); let private_key = Pkcs8PrivateKeyBytes::from(private_key.as_bytes()); - let private_key = AsymmetricCryptoKey::from_der(&private_key).unwrap(); + let private_key = PrivateKey::from_der(&private_key).unwrap(); let decrypted: SymmetricCryptoKey = encrypted.decapsulate_key_unsigned(&private_key).unwrap(); @@ -1554,7 +1553,7 @@ mod tests { let key_store = client.internal.get_key_store(); let context = key_store.context(); assert!(context.has_symmetric_key(SymmetricKeyId::User)); - assert!(context.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey)); + assert!(context.has_private_key(PrivateKeyId::UserPrivateKey)); let login_method = client.internal.get_login_method().unwrap(); if let LoginMethod::User(UserLoginMethod::Username { email, diff --git a/crates/bitwarden-core/src/key_management/mod.rs b/crates/bitwarden-core/src/key_management/mod.rs index bd7c140a5..2ade2ac4f 100644 --- a/crates/bitwarden-core/src/key_management/mod.rs +++ b/crates/bitwarden-core/src/key_management/mod.rs @@ -50,8 +50,8 @@ key_ids! { Local(LocalId), } - #[asymmetric] - pub enum AsymmetricKeyId { + #[private] + pub enum PrivateKeyId { UserPrivateKey, #[local] Local(LocalId), @@ -64,7 +64,7 @@ key_ids! { Local(LocalId), } - pub KeyIds => SymmetricKeyId, AsymmetricKeyId, SigningKeyId; + pub KeyIds => SymmetricKeyId, PrivateKeyId, SigningKeyId; } /// This is a helper function to create a test KeyStore with a single user key. diff --git a/crates/bitwarden-core/src/platform/generate_fingerprint.rs b/crates/bitwarden-core/src/platform/generate_fingerprint.rs index 53f2c5206..f17b52131 100644 --- a/crates/bitwarden-core/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden-core/src/platform/generate_fingerprint.rs @@ -7,7 +7,7 @@ use bitwarden_encoding::B64; use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::{MissingPrivateKeyError, key_management::AsymmetricKeyId}; +use crate::{MissingPrivateKeyError, key_management::PrivateKeyId}; /// Request to generate a fingerprint. #[derive(Serialize, Deserialize, Debug)] @@ -66,7 +66,7 @@ pub(crate) fn generate_user_fingerprint( // FIXME: [PM-18110] This should be removed once the key store can handle public keys and // fingerprints #[allow(deprecated)] - let private_key = ctx.dangerous_get_asymmetric_key(AsymmetricKeyId::UserPrivateKey)?; + let private_key = ctx.dangerous_get_private_key(PrivateKeyId::UserPrivateKey)?; let public_key = private_key.to_public_key().to_der()?; let fingerprint = fingerprint(&fingerprint_material, &public_key)?; diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index b748987fe..d40a2a955 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -7,8 +7,8 @@ use serde::Deserialize; use super::{from_b64_vec, split_enc_string}; use crate::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, RawPrivateKey, - RawPublicKey, SymmetricCryptoKey, + BitwardenLegacyKeyBytes, PrivateKey, PublicKey, RawPrivateKey, RawPublicKey, + SymmetricCryptoKey, error::{CryptoError, EncStringParseError, Result}, rsa::encrypt_rsa2048_oaep_sha1, }; @@ -164,7 +164,7 @@ impl UnsignedSharedKey { /// and thus does not guarantee sender authenticity. pub fn encapsulate_key_unsigned( encapsulated_key: &SymmetricCryptoKey, - encapsulation_key: &AsymmetricPublicCryptoKey, + encapsulation_key: &PublicKey, ) -> Result { match encapsulation_key.inner() { RawPublicKey::RsaOaepSha1(rsa_public_key) => { @@ -197,7 +197,7 @@ impl UnsignedSharedKey { /// guaranteed. pub fn decapsulate_key_unsigned( &self, - decapsulation_key: &AsymmetricCryptoKey, + decapsulation_key: &PrivateKey, ) -> Result { match decapsulation_key.inner() { RawPrivateKey::RsaOaepSha1(rsa_private_key) => { @@ -243,7 +243,7 @@ mod tests { use schemars::schema_for; use super::UnsignedSharedKey; - use crate::{AsymmetricCryptoKey, SymmetricCryptoKey}; + use crate::{PrivateKey, SymmetricCryptoKey}; const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS @@ -276,7 +276,7 @@ XKZBokBGnjFnTnKcs7nv/O8= #[test] fn test_enc_string_rsa2048_oaep_sha256_b64() { - let key_pair = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); + let key_pair = PrivateKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "3.SUx5gWrgmAKs/S1BoQrqOmx2Hl5fPVBVHokW17Flvm4TpBnJJRkfoitp7Jc4dfazPYjWGlckJz6X+qe+/AWilS1mxtzS0PmDy7tS5xP0GRlB39dstCd5jDw1wPmTbXiLcQ5VTvzpRAfRMEYVveTsEvVTByvEYAGSn4TnCsUDykyhRbD0YcJ4r1KHLs1b3BCBy2M1Gl5nmwckH08CAXaf8VfuBFStAGRKueovqp4euneQla+4G4fXdVvb8qKPnu0iVuALIE6nUNmeOiA3xN3d+akMxbbGxrQ1Ca4TYWjHVdj9C6abngQHkjKNYQwGUXrYo160hP4LIHn/huK6bZe5dQ=="; let enc_string: UnsignedSharedKey = enc_str.parse().unwrap(); @@ -289,7 +289,7 @@ XKZBokBGnjFnTnKcs7nv/O8= #[test] fn test_enc_string_rsa2048_oaep_sha1_b64() { - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); + let private_key = PrivateKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "4.DMD1D5r6BsDDd7C/FE1eZbMCKrmryvAsCKj6+bO54gJNUxisOI7SDcpPLRXf+JdhqY15pT+wimQ5cD9C+6OQ6s71LFQHewXPU29l9Pa1JxGeiKqp37KLYf+1IS6UB2K3ANN35C52ZUHh2TlzIS5RuntxnpCw7APbcfpcnmIdLPJBtuj/xbFd6eBwnI3GSe5qdS6/Ixdd0dgsZcpz3gHJBKmIlSo0YN60SweDq3kTJwox9xSqdCueIDg5U4khc7RhjYx8b33HXaNJj3DwgIH8iLj+lqpDekogr630OhHG3XRpvl4QzYO45bmHb8wAh67Dj70nsZcVg6bAEFHdSFohww=="; let enc_string: UnsignedSharedKey = enc_str.parse().unwrap(); @@ -302,7 +302,7 @@ XKZBokBGnjFnTnKcs7nv/O8= #[test] fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); + let private_key = PrivateKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "6.DMD1D5r6BsDDd7C/FE1eZbMCKrmryvAsCKj6+bO54gJNUxisOI7SDcpPLRXf+JdhqY15pT+wimQ5cD9C+6OQ6s71LFQHewXPU29l9Pa1JxGeiKqp37KLYf+1IS6UB2K3ANN35C52ZUHh2TlzIS5RuntxnpCw7APbcfpcnmIdLPJBtuj/xbFd6eBwnI3GSe5qdS6/Ixdd0dgsZcpz3gHJBKmIlSo0YN60SweDq3kTJwox9xSqdCueIDg5U4khc7RhjYx8b33HXaNJj3DwgIH8iLj+lqpDekogr630OhHG3XRpvl4QzYO45bmHb8wAh67Dj70nsZcVg6bAEFHdSFohww==|AA=="; let enc_string: UnsignedSharedKey = enc_str.parse().unwrap(); diff --git a/crates/bitwarden-crypto/src/keys/device_key.rs b/crates/bitwarden-crypto/src/keys/device_key.rs index a9b8be12d..f8a7cf469 100644 --- a/crates/bitwarden-crypto/src/keys/device_key.rs +++ b/crates/bitwarden-crypto/src/keys/device_key.rs @@ -1,6 +1,6 @@ use bitwarden_encoding::B64; -use super::{AsymmetricCryptoKey, PublicKeyEncryptionAlgorithm}; +use super::{PrivateKey, PublicKeyEncryptionAlgorithm}; use crate::{ CryptoError, EncString, KeyDecryptable, KeyEncryptable, Pkcs8PrivateKeyBytes, SymmetricCryptoKey, UnsignedSharedKey, error::Result, @@ -35,8 +35,7 @@ impl DeviceKey { pub fn trust_device(user_key: &SymmetricCryptoKey) -> Result { let device_key = DeviceKey(SymmetricCryptoKey::make_aes256_cbc_hmac_key()); - let device_private_key = - AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); + let device_private_key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); let protected_user_key = UnsignedSharedKey::encapsulate_key_unsigned( user_key, @@ -68,7 +67,7 @@ impl DeviceKey { ) -> Result { let device_private_key: Vec = protected_device_private_key.decrypt_with_key(&self.0)?; let device_private_key = Pkcs8PrivateKeyBytes::from(device_private_key); - let device_private_key = AsymmetricCryptoKey::from_der(&device_private_key)?; + let device_private_key = PrivateKey::from_der(&device_private_key)?; let user_key: SymmetricCryptoKey = protected_user_key.decapsulate_key_unsigned(&device_private_key)?; diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 5fbe667dd..99a7a7627 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -12,11 +12,9 @@ pub use symmetric_crypto_key::{ Aes256CbcHmacKey, Aes256CbcKey, EncodedSymmetricKey, SymmetricCryptoKey, SymmetricKeyAlgorithm, XChaCha20Poly1305Key, }; -mod asymmetric_crypto_key; -pub use asymmetric_crypto_key::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, PublicKeyEncryptionAlgorithm, -}; -pub(crate) use asymmetric_crypto_key::{RawPrivateKey, RawPublicKey}; +mod public_key_encryption; +pub use public_key_encryption::{PrivateKey, PublicKey, PublicKeyEncryptionAlgorithm}; +pub(crate) use public_key_encryption::{RawPrivateKey, RawPublicKey}; mod signed_public_key; pub use signed_public_key::{SignedPublicKey, SignedPublicKeyMessage}; mod user_key; diff --git a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/public_key_encryption.rs similarity index 92% rename from crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs rename to crates/bitwarden-crypto/src/keys/public_key_encryption.rs index 75b1907c2..77d88f8af 100644 --- a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/public_key_encryption.rs @@ -25,18 +25,18 @@ pub(crate) enum RawPublicKey { /// Public key of a key pair used in a public key encryption scheme. It is used for /// encrypting data. #[derive(Clone, PartialEq)] -pub struct AsymmetricPublicCryptoKey { +pub struct PublicKey { inner: RawPublicKey, } -impl AsymmetricPublicCryptoKey { +impl PublicKey { pub(crate) fn inner(&self) -> &RawPublicKey { &self.inner } /// Build a public key from the SubjectPublicKeyInfo DER. pub fn from_der(der: &SpkiPublicKeyBytes) -> Result { - Ok(AsymmetricPublicCryptoKey { + Ok(PublicKey { inner: RawPublicKey::RsaOaepSha1( RsaPublicKey::from_public_key_der(der.as_ref()) .map_err(|_| CryptoError::InvalidKey)?, @@ -70,7 +70,7 @@ pub(crate) enum RawPrivateKey { /// Private key of a key pair used in a public key encryption scheme. It is used for /// decrypting data that was encrypted with the corresponding public key. #[derive(Clone)] -pub struct AsymmetricCryptoKey { +pub struct PrivateKey { inner: RawPrivateKey, } @@ -80,10 +80,10 @@ const _: fn() = || { fn assert_zeroize_on_drop() {} assert_zeroize_on_drop::(); }; -impl zeroize::ZeroizeOnDrop for AsymmetricCryptoKey {} -impl CryptoKey for AsymmetricCryptoKey {} +impl zeroize::ZeroizeOnDrop for PrivateKey {} +impl CryptoKey for PrivateKey {} -impl AsymmetricCryptoKey { +impl PrivateKey { /// Generate a random AsymmetricCryptoKey (RSA-2048). pub fn make(algorithm: PublicKeyEncryptionAlgorithm) -> Self { Self::make_internal(algorithm, &mut rand::thread_rng()) @@ -139,9 +139,9 @@ impl AsymmetricCryptoKey { /// Derives the public key corresponding to this private key. This is deterministic /// and always derives the same public key. - pub fn to_public_key(&self) -> AsymmetricPublicCryptoKey { + pub fn to_public_key(&self) -> PublicKey { match &self.inner { - RawPrivateKey::RsaOaepSha1(private_key) => AsymmetricPublicCryptoKey { + RawPrivateKey::RsaOaepSha1(private_key) => PublicKey { inner: RawPublicKey::RsaOaepSha1(private_key.to_public_key()), }, } @@ -153,7 +153,7 @@ impl AsymmetricCryptoKey { } // We manually implement these to make sure we don't print any sensitive data -impl std::fmt::Debug for AsymmetricCryptoKey { +impl std::fmt::Debug for PrivateKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("AsymmetricCryptoKey").finish() } @@ -165,8 +165,8 @@ mod tests { use bitwarden_encoding::B64; use crate::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, Pkcs8PrivateKeyBytes, SpkiPublicKeyBytes, - SymmetricCryptoKey, UnsignedSharedKey, + Pkcs8PrivateKeyBytes, PrivateKey, PublicKey, SpkiPublicKeyBytes, SymmetricCryptoKey, + UnsignedSharedKey, content_format::{Bytes, Pkcs8PrivateKeyDerContentFormat}, }; @@ -205,10 +205,10 @@ DnqOsltgPomWZ7xVfMkm9niL2OA= let der_key_vec: Vec = der_key.into(); // Load the two different formats and check they are the same key - let pem_key = AsymmetricCryptoKey::from_pem(pem_key_str).unwrap(); - let der_key = AsymmetricCryptoKey::from_der( - &Bytes::::from(der_key_vec.clone()), - ) + let pem_key = PrivateKey::from_pem(pem_key_str).unwrap(); + let der_key = PrivateKey::from_der(&Bytes::::from( + der_key_vec.clone(), + )) .unwrap(); assert_eq!(pem_key.to_der().unwrap(), der_key.to_der().unwrap()); @@ -264,9 +264,8 @@ DnqOsltgPomWZ7xVfMkm9niL2OA= .unwrap(); let private_key = Pkcs8PrivateKeyBytes::from(private_key.as_bytes()); - let private_key = AsymmetricCryptoKey::from_der(&private_key).unwrap(); - let public_key = - AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from(&public_key)).unwrap(); + let private_key = PrivateKey::from_der(&private_key).unwrap(); + let public_key = PublicKey::from_der(&SpkiPublicKeyBytes::from(&public_key)).unwrap(); let raw_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key(); let encrypted = UnsignedSharedKey::encapsulate_key_unsigned(&raw_key, &public_key).unwrap(); diff --git a/crates/bitwarden-crypto/src/keys/rotateable_key_set.rs b/crates/bitwarden-crypto/src/keys/rotateable_key_set.rs index fe1aad077..7e71d0ae0 100644 --- a/crates/bitwarden-crypto/src/keys/rotateable_key_set.rs +++ b/crates/bitwarden-crypto/src/keys/rotateable_key_set.rs @@ -1,9 +1,9 @@ use serde::{Deserialize, Serialize}; use crate::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, CryptoError, EncString, KeyDecryptable, - KeyEncryptable, KeyIds, KeyStoreContext, Pkcs8PrivateKeyBytes, SpkiPublicKeyBytes, - SymmetricCryptoKey, UnsignedSharedKey, + CryptoError, EncString, KeyDecryptable, KeyEncryptable, KeyIds, KeyStoreContext, + Pkcs8PrivateKeyBytes, PrivateKey, PublicKey, SpkiPublicKeyBytes, SymmetricCryptoKey, + UnsignedSharedKey, }; /// A set of keys where a given `DownstreamKey` is protected by an encrypted public/private @@ -41,7 +41,7 @@ impl RotateableKeySet { upstream_key: &SymmetricCryptoKey, downstream_key_id: Ids::Symmetric, ) -> Result { - let key_pair = AsymmetricCryptoKey::make(crate::PublicKeyEncryptionAlgorithm::RsaOaepSha1); + let key_pair = PrivateKey::make(crate::PublicKeyEncryptionAlgorithm::RsaOaepSha1); // This uses this deprecated method and other methods directly on the other keys // rather than the key store context because we don't want the keys to @@ -84,8 +84,7 @@ impl RotateableKeySet { let priv_key_bytes: Vec = self .encrypted_decapsulation_key .decrypt_with_key(upstream_key)?; - let decapsulation_key = - AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(priv_key_bytes))?; + let decapsulation_key = PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(priv_key_bytes))?; let downstream_key = self .encapsulated_downstream_key .decapsulate_key_unsigned(&decapsulation_key)?; @@ -107,7 +106,7 @@ fn rotate_key_set( &key_set.encrypted_encapsulation_key, )?; let pub_key = SpkiPublicKeyBytes::from(pub_key_bytes); - let encapsulation_key = AsymmetricPublicCryptoKey::from_der(&pub_key)?; + let encapsulation_key = PublicKey::from_der(&pub_key)?; // TODO: There is no method to store only the public key in the store, so we // have pull out the downstream key to encapsulate it manually. #[allow(deprecated)] diff --git a/crates/bitwarden-crypto/src/keys/signed_public_key.rs b/crates/bitwarden-crypto/src/keys/signed_public_key.rs index 9a7e91adf..35dd72755 100644 --- a/crates/bitwarden-crypto/src/keys/signed_public_key.rs +++ b/crates/bitwarden-crypto/src/keys/signed_public_key.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; use serde_repr::{Deserialize_repr, Serialize_repr}; -use super::AsymmetricPublicCryptoKey; +use super::PublicKey; use crate::{ CoseSign1Bytes, CryptoError, PublicKeyEncryptionAlgorithm, RawPublicKey, SignedObject, SigningKey, SigningNamespace, SpkiPublicKeyBytes, VerifyingKey, cose::CoseSerializable, @@ -52,7 +52,7 @@ pub struct SignedPublicKeyMessage { impl SignedPublicKeyMessage { /// Creates a new `SignedPublicKeyMessage` from an `AsymmetricPublicCryptoKey`. This message /// can then be signed using a `SigningKey` to create a `SignedPublicKey`. - pub fn from_public_key(public_key: &AsymmetricPublicCryptoKey) -> Result { + pub fn from_public_key(public_key: &PublicKey) -> Result { match public_key.inner() { RawPublicKey::RsaOaepSha1(_) => Ok(SignedPublicKeyMessage { algorithm: PublicKeyEncryptionAlgorithm::RsaOaepSha1, @@ -100,10 +100,7 @@ impl From for String { impl SignedPublicKey { /// Verifies the signature of the public key against the provided `VerifyingKey`, and returns /// the `AsymmetricPublicCryptoKey` if the verification is successful. - pub fn verify_and_unwrap( - self, - verifying_key: &VerifyingKey, - ) -> Result { + pub fn verify_and_unwrap(self, verifying_key: &VerifyingKey) -> Result { let public_key_message: SignedPublicKeyMessage = self .0 .verify_and_unwrap(verifying_key, &SigningNamespace::SignedPublicKey)?; @@ -111,12 +108,12 @@ impl SignedPublicKey { public_key_message.algorithm, public_key_message.content_format, ) { - (PublicKeyEncryptionAlgorithm::RsaOaepSha1, PublicKeyFormat::Spki) => Ok( - AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from( + (PublicKeyEncryptionAlgorithm::RsaOaepSha1, PublicKeyFormat::Spki) => { + Ok(PublicKey::from_der(&SpkiPublicKeyBytes::from( public_key_message.public_key.into_vec(), )) - .map_err(|_| EncodingError::InvalidValue("public key"))?, - ), + .map_err(|_| EncodingError::InvalidValue("public key"))?) + } } } } @@ -162,12 +159,12 @@ impl schemars::JsonSchema for SignedPublicKey { #[cfg(test)] mod tests { use super::*; - use crate::{AsymmetricCryptoKey, PublicKeyEncryptionAlgorithm, SignatureAlgorithm}; + use crate::{PrivateKey, PublicKeyEncryptionAlgorithm, SignatureAlgorithm}; #[test] fn test_signed_asymmetric_public_key() { let public_key = - AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1).to_public_key(); + PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1).to_public_key(); let signing_key = SigningKey::make(SignatureAlgorithm::Ed25519); let message = SignedPublicKeyMessage::from_public_key(&public_key).unwrap(); let signed_public_key = message.sign(&signing_key).unwrap(); diff --git a/crates/bitwarden-crypto/src/store/context.rs b/crates/bitwarden-crypto/src/store/context.rs index 8afdcb9dc..95ee2b50f 100644 --- a/crates/bitwarden-crypto/src/store/context.rs +++ b/crates/bitwarden-crypto/src/store/context.rs @@ -9,10 +9,10 @@ use zeroize::Zeroizing; use super::KeyStoreInner; use crate::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, ContentFormat, - CoseEncrypt0Bytes, CoseKeyBytes, CoseSerializable, CryptoError, EncString, KeyDecryptable, - KeyEncryptable, KeyId, KeyIds, LocalId, Pkcs8PrivateKeyBytes, PublicKeyEncryptionAlgorithm, - Result, RotatedUserKeys, Signature, SignatureAlgorithm, SignedObject, SignedPublicKey, + BitwardenLegacyKeyBytes, ContentFormat, CoseEncrypt0Bytes, CoseKeyBytes, CoseSerializable, + CryptoError, EncString, KeyDecryptable, KeyEncryptable, KeyId, KeyIds, LocalId, + Pkcs8PrivateKeyBytes, PrivateKey, PublicKey, PublicKeyEncryptionAlgorithm, Result, + RotatedUserKeys, Signature, SignatureAlgorithm, SignedObject, SignedPublicKey, SignedPublicKeyMessage, SigningKey, SymmetricCryptoKey, SymmetricKeyAlgorithm, UnsignedSharedKey, VerifyingKey, derive_shareable_key, error::UnsupportedOperationError, signing, store::backend::StoreBackend, @@ -44,8 +44,8 @@ use crate::{ /// # #[local] /// # Local(LocalId), /// # } -/// # #[asymmetric] -/// # pub enum AsymmKeyId { +/// # #[private] +/// # pub enum PrivateKeyId { /// # UserPrivate, /// # #[local] /// # Local(LocalId), @@ -56,7 +56,7 @@ use crate::{ /// # #[local] /// # Local(LocalId), /// # } -/// # pub Ids => SymmKeyId, AsymmKeyId, SigningKeyId; +/// # pub Ids => SymmKeyId, PrivateKeyId, SigningKeyId; /// # } /// struct Data { /// key: EncString, @@ -81,7 +81,7 @@ pub struct KeyStoreContext<'a, Ids: KeyIds> { pub(super) global_keys: GlobalKeys<'a, Ids>, pub(super) local_symmetric_keys: Box>, - pub(super) local_asymmetric_keys: Box>, + pub(super) local_private_keys: Box>, pub(super) local_signing_keys: Box>, pub(super) security_state_version: u64, @@ -135,7 +135,7 @@ impl KeyStoreContext<'_, Ids> { /// To clear the global keys, you need to use [super::KeyStore::clear] instead. pub fn clear_local(&mut self) { self.local_symmetric_keys.clear(); - self.local_asymmetric_keys.clear(); + self.local_private_keys.clear(); self.local_signing_keys.clear(); } @@ -155,13 +155,13 @@ impl KeyStoreContext<'_, Ids> { self.local_symmetric_keys.retain(f); } - /// Remove all asymmetric keys from the context for which the predicate returns false + /// Remove all private keys from the context for which the predicate returns false /// This will also remove the keys from the global store if this context has write access - pub fn retain_asymmetric_keys(&mut self, f: fn(Ids::Asymmetric) -> bool) { + pub fn retain_private_keys(&mut self, f: fn(Ids::Private) -> bool) { if let Ok(keys) = self.global_keys.get_mut() { - keys.asymmetric_keys.retain(f); + keys.private_keys.retain(f); } - self.local_asymmetric_keys.retain(f); + self.local_private_keys.retain(f); } fn drop_symmetric_key(&mut self, key_id: Ids::Symmetric) -> Result<()> { @@ -173,11 +173,11 @@ impl KeyStoreContext<'_, Ids> { Ok(()) } - fn drop_asymmetric_key(&mut self, key_id: Ids::Asymmetric) -> Result<()> { + fn drop_private_key(&mut self, key_id: Ids::Private) -> Result<()> { if key_id.is_local() { - self.local_asymmetric_keys.remove(key_id); + self.local_private_keys.remove(key_id); } else { - self.global_keys.get_mut()?.asymmetric_keys.remove(key_id); + self.global_keys.get_mut()?.private_keys.remove(key_id); } Ok(()) } @@ -272,25 +272,21 @@ impl KeyStoreContext<'_, Ids> { Ok(()) } - /// Move an asymmetric key from a local identifier to a global identifier within the context + /// Move a private key from a local identifier to a global identifier within the context /// /// The key value is copied to `to` and the original identifier `from` is removed. /// /// # Errors /// Returns an error if the source key does not exist or if setting the destination key /// fails (for example due to read-only global store). - pub fn persist_asymmetric_key( - &mut self, - from: Ids::Asymmetric, - to: Ids::Asymmetric, - ) -> Result<()> { + pub fn persist_private_key(&mut self, from: Ids::Private, to: Ids::Private) -> Result<()> { if !from.is_local() || to.is_local() { return Err(CryptoError::InvalidKeyStoreOperation); } - let key = self.get_asymmetric_key(from)?.to_owned(); - self.drop_asymmetric_key(from)?; + let key = self.get_private_key(from)?.to_owned(); + self.drop_private_key(from)?; #[allow(deprecated)] - self.set_asymmetric_key(to, key)?; + self.set_private_key(to, key)?; Ok(()) } @@ -339,10 +335,10 @@ impl KeyStoreContext<'_, Ids> { pub fn wrap_private_key( &self, wrapping_key: Ids::Symmetric, - key_to_wrap: Ids::Asymmetric, + key_to_wrap: Ids::Private, ) -> Result { let wrapping_key = self.get_symmetric_key(wrapping_key)?; - let private_key = self.get_asymmetric_key(key_to_wrap)?.to_owned(); + let private_key = self.get_private_key(key_to_wrap)?.to_owned(); private_key.to_der()?.encrypt_with_key(wrapping_key) } @@ -358,12 +354,11 @@ impl KeyStoreContext<'_, Ids> { &mut self, wrapping_key: Ids::Symmetric, wrapped_key: &EncString, - ) -> Result { + ) -> Result { let wrapping_key = self.get_symmetric_key(wrapping_key)?; let private_key_bytes: Vec = wrapped_key.decrypt_with_key(wrapping_key)?; - let private_key = - AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(private_key_bytes))?; - self.add_local_asymmetric_key(private_key) + let private_key = PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(private_key_bytes))?; + self.add_local_private_key(private_key) } /// Decrypt and import a previously wrapped signing key into the context. @@ -402,13 +397,10 @@ impl KeyStoreContext<'_, Ids> { /// This converts the stored private key into its public key representation. /// /// # Errors - /// Returns an error if the asymmetric key id does not exist. - pub fn get_public_key( - &self, - asymmetric_key_id: Ids::Asymmetric, - ) -> Result { - let asymmetric_key = self.get_asymmetric_key(asymmetric_key_id)?; - Ok(asymmetric_key.to_public_key()) + /// Returns an error if the private key id does not exist. + pub fn get_public_key(&self, private_key_id: Ids::Private) -> Result { + let private_key = self.get_private_key(private_key_id)?; + Ok(private_key.to_public_key()) } /// Encrypt and return a symmetric key from the context by using an already existing symmetric @@ -472,11 +464,11 @@ impl KeyStoreContext<'_, Ids> { /// * `encapsulated_shared_key` - The symmetric key to decrypt pub fn decapsulate_key_unsigned( &mut self, - decapsulation_key: Ids::Asymmetric, + decapsulation_key: Ids::Private, new_key_id: Ids::Symmetric, encapsulated_shared_key: &UnsignedSharedKey, ) -> Result { - let decapsulation_key = self.get_asymmetric_key(decapsulation_key)?; + let decapsulation_key = self.get_private_key(decapsulation_key)?; let decapsulated_key = encapsulated_shared_key.decapsulate_key_unsigned(decapsulation_key)?; @@ -497,12 +489,12 @@ impl KeyStoreContext<'_, Ids> { /// * `shared_key` - The key id to encrypt. It must already exist in the context pub fn encapsulate_key_unsigned( &self, - encapsulation_key: Ids::Asymmetric, + encapsulation_key: Ids::Private, shared_key: Ids::Symmetric, ) -> Result { UnsignedSharedKey::encapsulate_key_unsigned( self.get_symmetric_key(shared_key)?, - &self.get_asymmetric_key(encapsulation_key)?.to_public_key(), + &self.get_private_key(encapsulation_key)?.to_public_key(), ) } @@ -511,9 +503,9 @@ impl KeyStoreContext<'_, Ids> { self.get_symmetric_key(key_id).is_ok() } - /// Returns `true` if the context has an asymmetric key with the given identifier - pub fn has_asymmetric_key(&self, key_id: Ids::Asymmetric) -> bool { - self.get_asymmetric_key(key_id).is_ok() + /// Returns `true` if the context has a private key with the given identifier + pub fn has_private_key(&self, key_id: Ids::Private) -> bool { + self.get_private_key(key_id).is_ok() } /// Returns `true` if the context has a signing key with the given identifier @@ -537,8 +529,8 @@ impl KeyStoreContext<'_, Ids> { pub fn make_private_key( &mut self, algorithm: PublicKeyEncryptionAlgorithm, - ) -> Result { - self.add_local_asymmetric_key(AsymmetricCryptoKey::make(algorithm)) + ) -> Result { + self.add_local_private_key(PrivateKey::make(algorithm)) } /// Makes a new signing key using the current default algorithm, and stores it in the context as @@ -547,13 +539,6 @@ impl KeyStoreContext<'_, Ids> { self.add_local_signing_key(SigningKey::make(algorithm)) } - /// Makes a new asymmetric encryption key using the current default algorithm, and stores it in - /// the context - pub fn make_asymmetric_key(&mut self) -> Result { - let key = AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); - self.add_local_asymmetric_key(key) - } - /// Derive a shareable key using hkdf from secret and name and store it in the context. /// /// A specialized variant of this function was called `CryptoService.makeSendKey` in the @@ -599,11 +584,8 @@ impl KeyStoreContext<'_, Ids> { /// # Errors /// Returns [`CryptoError::MissingKeyId`] if the key id does not exist in the context. #[deprecated(note = "This function should ideally never be used outside this crate")] - pub fn dangerous_get_asymmetric_key( - &self, - key_id: Ids::Asymmetric, - ) -> Result<&AsymmetricCryptoKey> { - self.get_asymmetric_key(key_id) + pub fn dangerous_get_private_key(&self, key_id: Ids::Private) -> Result<&PrivateKey> { + self.get_private_key(key_id) } /// Makes a signed public key from an asymmetric private key and signing key stored in context. @@ -611,10 +593,10 @@ impl KeyStoreContext<'_, Ids> { /// to share with you, they can use this public key. pub fn make_signed_public_key( &self, - private_key_id: Ids::Asymmetric, + private_key_id: Ids::Private, signing_key_id: Ids::Signing, ) -> Result { - let public_key = self.get_asymmetric_key(private_key_id)?.to_public_key(); + let public_key = self.get_private_key(private_key_id)?.to_public_key(); let signing_key = self.get_signing_key(signing_key_id)?; let signed_public_key = SignedPublicKeyMessage::from_public_key(&public_key)?.sign(signing_key)?; @@ -630,14 +612,11 @@ impl KeyStoreContext<'_, Ids> { .ok_or_else(|| crate::CryptoError::MissingKeyId(format!("{key_id:?}"))) } - pub(super) fn get_asymmetric_key( - &self, - key_id: Ids::Asymmetric, - ) -> Result<&AsymmetricCryptoKey> { + pub(super) fn get_private_key(&self, key_id: Ids::Private) -> Result<&PrivateKey> { if key_id.is_local() { - self.local_asymmetric_keys.get(key_id) + self.local_private_keys.get(key_id) } else { - self.global_keys.get().asymmetric_keys.get(key_id) + self.global_keys.get().private_keys.get(key_id) } .ok_or_else(|| crate::CryptoError::MissingKeyId(format!("{key_id:?}"))) } @@ -712,29 +691,19 @@ impl KeyStoreContext<'_, Ids> { /// Returns [`CryptoError::ReadOnlyKeyStore`] if attempting to write to the global store when /// the context is read-only. #[deprecated(note = "This function should ideally never be used outside this crate")] - pub fn set_asymmetric_key( - &mut self, - key_id: Ids::Asymmetric, - key: AsymmetricCryptoKey, - ) -> Result<()> { + pub fn set_private_key(&mut self, key_id: Ids::Private, key: PrivateKey) -> Result<()> { if key_id.is_local() { - self.local_asymmetric_keys.upsert(key_id, key); + self.local_private_keys.upsert(key_id, key); } else { - self.global_keys - .get_mut()? - .asymmetric_keys - .upsert(key_id, key); + self.global_keys.get_mut()?.private_keys.upsert(key_id, key); } Ok(()) } - /// Add a new asymmetric key to the local context, returning a new unique identifier for it. - pub fn add_local_asymmetric_key( - &mut self, - key: AsymmetricCryptoKey, - ) -> Result { - let key_id = Ids::Asymmetric::new_local(LocalId::new()); - self.local_asymmetric_keys.upsert(key_id, key); + /// Add a new private key to the local context, returning a new unique identifier for it. + pub fn add_local_private_key(&mut self, key: PrivateKey) -> Result { + let key_id = Ids::Private::new_local(LocalId::new()); + self.local_private_keys.upsert(key_id, key); Ok(key_id) } @@ -838,7 +807,7 @@ impl KeyStoreContext<'_, Ids> { /// Re-encrypts the user's keys with the provided symmetric key for a v2 user. pub fn dangerous_get_v2_rotated_account_keys( &self, - current_user_private_key_id: Ids::Asymmetric, + current_user_private_key_id: Ids::Private, current_user_signing_key_id: Ids::Signing, ) -> Result { crate::dangerous_get_v2_rotated_account_keys( @@ -855,10 +824,9 @@ mod tests { use serde::{Deserialize, Serialize}; use crate::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, CompositeEncryptable, CoseKeyBytes, - CoseSerializable, CryptoError, Decryptable, KeyDecryptable, Pkcs8PrivateKeyBytes, - SignatureAlgorithm, SigningKey, SigningNamespace, SymmetricCryptoKey, - SymmetricKeyAlgorithm, + CompositeEncryptable, CoseKeyBytes, CoseSerializable, CryptoError, Decryptable, + KeyDecryptable, Pkcs8PrivateKeyBytes, PrivateKey, PublicKey, SignatureAlgorithm, + SigningKey, SigningNamespace, SymmetricCryptoKey, SymmetricKeyAlgorithm, store::{ KeyStore, tests::{Data, DataView}, @@ -1055,7 +1023,7 @@ mod tests { // Public/Private key assert_eq!( - AsymmetricPublicCryptoKey::from_der(&rotated_keys.public_key) + PublicKey::from_der(&rotated_keys.public_key) .unwrap() .to_der() .unwrap(), @@ -1070,8 +1038,7 @@ mod tests { .decrypt_with_key(&rotated_keys.user_key) .unwrap(); let private_key = - AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(decrypted_private_key)) - .unwrap(); + PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(decrypted_private_key)).unwrap(); assert_eq!( private_key.to_der().unwrap(), ctx.get_asymmetric_key(current_user_private_key_id) diff --git a/crates/bitwarden-crypto/src/store/key_rotation.rs b/crates/bitwarden-crypto/src/store/key_rotation.rs index 9997321a8..8c8af33ba 100644 --- a/crates/bitwarden-crypto/src/store/key_rotation.rs +++ b/crates/bitwarden-crypto/src/store/key_rotation.rs @@ -22,13 +22,13 @@ pub struct RotatedUserKeys { /// Generates a new user key and re-encrypts the current private and signing keys with it. pub fn dangerous_get_v2_rotated_account_keys( - current_user_private_key_id: Ids::Asymmetric, + current_user_private_key_id: Ids::Private, current_user_signing_key_id: Ids::Signing, ctx: &KeyStoreContext, ) -> Result { let user_key = SymmetricCryptoKey::make_xchacha20_poly1305_key(); - let current_private_key = ctx.get_asymmetric_key(current_user_private_key_id)?; + let current_private_key = ctx.get_private_key(current_user_private_key_id)?; let current_signing_key = ctx.get_signing_key(current_user_signing_key_id)?; let current_public_key = ¤t_private_key.to_public_key(); @@ -49,8 +49,8 @@ pub fn dangerous_get_v2_rotated_account_keys( mod tests { use super::*; use crate::{ - AsymmetricCryptoKey, KeyDecryptable, KeyStore, Pkcs8PrivateKeyBytes, SignatureAlgorithm, - SigningKey, traits::tests::TestIds, + KeyDecryptable, KeyStore, Pkcs8PrivateKeyBytes, PrivateKey, SignatureAlgorithm, SigningKey, + traits::tests::TestIds, }; #[test] @@ -85,8 +85,7 @@ mod tests { .decrypt_with_key(&rotated_keys.user_key) .unwrap(); let private_key = - AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(decrypted_private_key)) - .unwrap(); + PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(decrypted_private_key)).unwrap(); assert_eq!( private_key.to_der().unwrap(), ctx.get_asymmetric_key(current_user_private_key_id) diff --git a/crates/bitwarden-crypto/src/store/mod.rs b/crates/bitwarden-crypto/src/store/mod.rs index 7e8901c19..83e188d36 100644 --- a/crates/bitwarden-crypto/src/store/mod.rs +++ b/crates/bitwarden-crypto/src/store/mod.rs @@ -111,7 +111,7 @@ impl std::fmt::Debug for KeyStore { struct KeyStoreInner { symmetric_keys: Box>, - asymmetric_keys: Box>, + private_keys: Box>, signing_keys: Box>, security_state_version: u64, } @@ -122,7 +122,7 @@ impl Default for KeyStore { Self { inner: Arc::new(RwLock::new(KeyStoreInner { symmetric_keys: create_store(), - asymmetric_keys: create_store(), + private_keys: create_store(), signing_keys: create_store(), security_state_version: 1, })), @@ -136,7 +136,7 @@ impl KeyStore { pub fn clear(&self) { let mut keys = self.inner.write().expect("RwLock is poisoned"); keys.symmetric_keys.clear(); - keys.asymmetric_keys.clear(); + keys.private_keys.clear(); keys.signing_keys.clear(); } @@ -183,7 +183,7 @@ impl KeyStore { KeyStoreContext { global_keys: GlobalKeys::ReadOnly(data), local_symmetric_keys: create_store(), - local_asymmetric_keys: create_store(), + local_private_keys: create_store(), local_signing_keys: create_store(), security_state_version, _phantom: std::marker::PhantomData, @@ -216,7 +216,7 @@ impl KeyStore { KeyStoreContext { global_keys: GlobalKeys::ReadWrite(inner), local_symmetric_keys: create_store(), - local_asymmetric_keys: create_store(), + local_private_keys: create_store(), local_signing_keys: create_store(), security_state_version, _phantom: std::marker::PhantomData, diff --git a/crates/bitwarden-crypto/src/traits/encryptable.rs b/crates/bitwarden-crypto/src/traits/encryptable.rs index 45ba5bed3..ebce60949 100644 --- a/crates/bitwarden-crypto/src/traits/encryptable.rs +++ b/crates/bitwarden-crypto/src/traits/encryptable.rs @@ -169,7 +169,7 @@ impl KeyStore { let store = KeyStore::::default(); - let asymm_key = AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); + let asymm_key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); let mut ctx = store.context_mut(); let local_key_id = ctx.make_symmetric_key(SymmetricKeyAlgorithm::Aes256CbcHmac); diff --git a/crates/bitwarden-crypto/src/traits/key_id.rs b/crates/bitwarden-crypto/src/traits/key_id.rs index 9d24f5612..fe26d8d69 100644 --- a/crates/bitwarden-crypto/src/traits/key_id.rs +++ b/crates/bitwarden-crypto/src/traits/key_id.rs @@ -2,7 +2,7 @@ use std::{fmt::Debug, hash::Hash}; use zeroize::ZeroizeOnDrop; -use crate::{AsymmetricCryptoKey, CryptoKey, SigningKey, SymmetricCryptoKey}; +use crate::{CryptoKey, PrivateKey, SigningKey, SymmetricCryptoKey}; /// Represents a key identifier that can be used to identify cryptographic keys in the /// key store. It is used to avoid exposing the key material directly in the public API. @@ -35,7 +35,7 @@ pub trait KeyIds { #[allow(missing_docs)] type Symmetric: KeyId; #[allow(missing_docs)] - type Asymmetric: KeyId; + type Private: KeyId; /// Signing keys are used to create detached signatures and to sign objects. type Signing: KeyId; } @@ -64,8 +64,8 @@ impl LocalId { /// Local(LocalId), /// } /// -/// #[asymmetric] -/// pub enum AsymmKeyId { +/// #[private] +/// pub enum PrivateKeyId { /// PrivateKey, /// #[local] /// Local(LocalId), @@ -78,7 +78,7 @@ impl LocalId { /// Local(LocalId), /// } /// -/// pub Ids => SymmKeyId, AsymmKeyId, SigningKeyId; +/// pub Ids => SymmKeyId, PrivateKeyId, SigningKeyId; /// } #[macro_export] macro_rules! key_ids { @@ -92,7 +92,7 @@ macro_rules! key_ids { $(,)? } )+ - $ids_vis:vis $ids_name:ident => $symm_name:ident, $asymm_name:ident, $signing_name:ident; + $ids_vis:vis $ids_name:ident => $symm_name:ident, $private_name:ident, $signing_name:ident; ) => { use $crate::LocalId; @@ -127,13 +127,13 @@ macro_rules! key_ids { $ids_vis struct $ids_name; impl $crate::KeyIds for $ids_name { type Symmetric = $symm_name; - type Asymmetric = $asymm_name; + type Private = $private_name; type Signing = $signing_name; } }; ( @key_type symmetric ) => { $crate::SymmetricCryptoKey }; - ( @key_type asymmetric ) => { $crate::AsymmetricCryptoKey }; + ( @key_type private ) => { $crate::PrivateKey }; ( @key_type signing ) => { $crate::SigningKey }; ( @variant_match $variant:ident ( $inner:ty ) ) => { $variant (_) }; @@ -162,9 +162,9 @@ pub(crate) mod tests { assert!(!TestSymmKey::B((4, 10)).is_local()); assert!(TestSymmKey::C(local).is_local()); - assert!(!TestAsymmKey::A(0).is_local()); - assert!(!TestAsymmKey::B.is_local()); - assert!(TestAsymmKey::C(local).is_local()); + assert!(!TestPrivateKey::A(0).is_local()); + assert!(!TestPrivateKey::B.is_local()); + assert!(TestPrivateKey::C(local).is_local()); assert!(!TestSigningKey::A(0).is_local()); assert!(!TestSigningKey::B.is_local()); diff --git a/crates/bitwarden-wasm-internal/src/pure_crypto.rs b/crates/bitwarden-wasm-internal/src/pure_crypto.rs index 40ef41278..eb136e524 100644 --- a/crates/bitwarden-wasm-internal/src/pure_crypto.rs +++ b/crates/bitwarden-wasm-internal/src/pure_crypto.rs @@ -4,11 +4,11 @@ use bitwarden_core::key_management::KeyIds; #[allow(deprecated)] use bitwarden_crypto::dangerous_derive_kdf_material; use bitwarden_crypto::{ - AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, CoseKeyBytes, - CoseSerializable, CoseSign1Bytes, CryptoError, Decryptable, EncString, Kdf, KeyDecryptable, - KeyEncryptable, KeyStore, MasterKey, OctetStreamBytes, Pkcs8PrivateKeyBytes, - PrimitiveEncryptable, PublicKeyEncryptionAlgorithm, SignatureAlgorithm, SignedPublicKey, - SigningKey, SpkiPublicKeyBytes, SymmetricCryptoKey, UnsignedSharedKey, VerifyingKey, + BitwardenLegacyKeyBytes, CoseKeyBytes, CoseSerializable, CoseSign1Bytes, CryptoError, + Decryptable, EncString, Kdf, KeyDecryptable, KeyEncryptable, KeyStore, MasterKey, + OctetStreamBytes, Pkcs8PrivateKeyBytes, PrimitiveEncryptable, PrivateKey, PublicKey, + PublicKeyEncryptionAlgorithm, SignatureAlgorithm, SignedPublicKey, SigningKey, + SpkiPublicKeyBytes, SymmetricCryptoKey, UnsignedSharedKey, VerifyingKey, }; use rsa::{ Oaep, RsaPrivateKey, RsaPublicKey, @@ -239,8 +239,7 @@ impl PureCrypto { shared_key: Vec, encapsulation_key: Vec, ) -> Result { - let encapsulation_key = - AsymmetricPublicCryptoKey::from_der(&SpkiPublicKeyBytes::from(encapsulation_key))?; + let encapsulation_key = PublicKey::from_der(&SpkiPublicKeyBytes::from(encapsulation_key))?; Ok(UnsignedSharedKey::encapsulate_key_unsigned( &SymmetricCryptoKey::try_from(&BitwardenLegacyKeyBytes::from(shared_key))?, &encapsulation_key, @@ -256,9 +255,9 @@ impl PureCrypto { decapsulation_key: Vec, ) -> Result, CryptoError> { Ok(UnsignedSharedKey::from_str(encapsulated_key.as_str())? - .decapsulate_key_unsigned(&AsymmetricCryptoKey::from_der( - &Pkcs8PrivateKeyBytes::from(decapsulation_key), - )?)? + .decapsulate_key_unsigned(&PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from( + decapsulation_key, + ))?)? .to_encoded() .to_vec()) } @@ -328,7 +327,7 @@ impl PureCrypto { /// returns the corresponding public RSA key in DER format. /// HAZMAT WARNING: Do not use outside of implementing cryptofunctionservice pub fn rsa_extract_public_key(private_key: Vec) -> Result, RsaError> { - let private_key = AsymmetricCryptoKey::from_der(&Pkcs8PrivateKeyBytes::from(private_key)) + let private_key = PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(private_key)) .map_err(|_| RsaError::KeyParse)?; let public_key = private_key.to_public_key(); Ok(public_key @@ -340,7 +339,7 @@ impl PureCrypto { /// Generates a new RSA key pair and returns the private key /// HAZMAT WARNING: Do not use outside of implementing cryptofunctionservice pub fn rsa_generate_keypair() -> Result, RsaError> { - let private_key = AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); + let private_key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); Ok(private_key .to_der() .map_err(|_| RsaError::KeySerialize)? @@ -614,7 +613,7 @@ DnqOsltgPomWZ7xVfMkm9niL2OA= #[test] fn test_wrap_encapsulation_key() { - let decapsulation_key = AsymmetricCryptoKey::from_pem(PEM_KEY).unwrap(); + let decapsulation_key = PrivateKey::from_pem(PEM_KEY).unwrap(); let encapsulation_key = decapsulation_key .to_public_key() .to_der() @@ -632,7 +631,7 @@ DnqOsltgPomWZ7xVfMkm9niL2OA= #[test] fn test_wrap_decapsulation_key() { - let decapsulation_key = AsymmetricCryptoKey::from_pem(PEM_KEY).unwrap(); + let decapsulation_key = PrivateKey::from_pem(PEM_KEY).unwrap(); let wrapping_key = PureCrypto::make_user_key_aes256_cbc_hmac(); let wrapped_key = PureCrypto::wrap_decapsulation_key( decapsulation_key.to_der().unwrap().to_vec(), @@ -647,7 +646,7 @@ DnqOsltgPomWZ7xVfMkm9niL2OA= #[test] fn test_encapsulate_key_unsigned() { let shared_key = PureCrypto::make_user_key_aes256_cbc_hmac(); - let decapsulation_key = AsymmetricCryptoKey::from_pem(PEM_KEY).unwrap(); + let decapsulation_key = PrivateKey::from_pem(PEM_KEY).unwrap(); let encapsulation_key = decapsulation_key.to_public_key().to_der().unwrap(); let encapsulated_key = PureCrypto::encapsulate_key_unsigned( shared_key.clone(), diff --git a/crates/memory-testing/src/main.rs b/crates/memory-testing/src/main.rs index 96070b216..91bb8638e 100644 --- a/crates/memory-testing/src/main.rs +++ b/crates/memory-testing/src/main.rs @@ -31,7 +31,7 @@ fn main() { symmetric_keys.push((key.to_encoded(), key)); } memory_testing::CaseCommand::AsymmetricKey { private_key } => { - let key = bitwarden_crypto::AsymmetricCryptoKey::from_pem(&private_key).unwrap(); + let key = bitwarden_crypto::PrivateKey::from_pem(&private_key).unwrap(); asymmetric_keys.push(key); } memory_testing::CaseCommand::MasterKey { From d03fcc442935f3f28ebd38c655ee7a8f47248cba Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 18 Dec 2025 18:23:58 +0100 Subject: [PATCH 2/4] Fix build --- .../examples/protect_key_with_password.rs | 6 +++--- crates/bitwarden-crypto/examples/seal_struct.rs | 6 +++--- crates/bitwarden-crypto/src/store/context.rs | 15 +++++++++------ crates/bitwarden-crypto/src/store/key_rotation.rs | 14 ++++++++------ crates/bitwarden-crypto/src/traits/encryptable.rs | 2 +- crates/bitwarden-crypto/src/traits/key_id.rs | 2 +- crates/bitwarden-crypto/src/traits/mod.rs | 6 +++--- 7 files changed, 28 insertions(+), 23 deletions(-) diff --git a/crates/bitwarden-crypto/examples/protect_key_with_password.rs b/crates/bitwarden-crypto/examples/protect_key_with_password.rs index cc96df8e7..74087be25 100644 --- a/crates/bitwarden-crypto/examples/protect_key_with_password.rs +++ b/crates/bitwarden-crypto/examples/protect_key_with_password.rs @@ -90,8 +90,8 @@ key_ids! { VaultKey(LocalId) } - #[asymmetric] - pub enum ExampleAsymmetricKey { + #[private] + pub enum ExamplePrivateKey { Key(u8), #[local] Local(LocalId) @@ -104,5 +104,5 @@ key_ids! { Local(LocalId) } - pub ExampleIds => ExampleSymmetricKey, ExampleAsymmetricKey, ExampleSigningKey; + pub ExampleIds => ExampleSymmetricKey, ExamplePrivateKey, ExampleSigningKey; } diff --git a/crates/bitwarden-crypto/examples/seal_struct.rs b/crates/bitwarden-crypto/examples/seal_struct.rs index a86b3bd83..792881c8e 100644 --- a/crates/bitwarden-crypto/examples/seal_struct.rs +++ b/crates/bitwarden-crypto/examples/seal_struct.rs @@ -98,8 +98,8 @@ key_ids! { ItemKey(LocalId) } - #[asymmetric] - pub enum ExampleAsymmetricKey { + #[private] + pub enum ExamplePrivateKey { Key(u8), #[local] Local(LocalId), @@ -111,5 +111,5 @@ key_ids! { #[local] Local(LocalId), } - pub ExampleIds => ExampleSymmetricKey, ExampleAsymmetricKey, ExampleSigningKey; + pub ExampleIds => ExampleSymmetricKey, ExamplePrivateKey, ExampleSigningKey; } diff --git a/crates/bitwarden-crypto/src/store/context.rs b/crates/bitwarden-crypto/src/store/context.rs index 95ee2b50f..72591cd1e 100644 --- a/crates/bitwarden-crypto/src/store/context.rs +++ b/crates/bitwarden-crypto/src/store/context.rs @@ -825,8 +825,9 @@ mod tests { use crate::{ CompositeEncryptable, CoseKeyBytes, CoseSerializable, CryptoError, Decryptable, - KeyDecryptable, Pkcs8PrivateKeyBytes, PrivateKey, PublicKey, SignatureAlgorithm, - SigningKey, SigningNamespace, SymmetricCryptoKey, SymmetricKeyAlgorithm, + KeyDecryptable, Pkcs8PrivateKeyBytes, PrivateKey, PublicKey, PublicKeyEncryptionAlgorithm, + SignatureAlgorithm, SigningKey, SigningNamespace, SymmetricCryptoKey, + SymmetricKeyAlgorithm, store::{ KeyStore, tests::{Data, DataView}, @@ -1011,7 +1012,9 @@ mod tests { // Make the keys let current_user_signing_key_id = ctx.make_signing_key(SignatureAlgorithm::Ed25519).unwrap(); - let current_user_private_key_id = ctx.make_asymmetric_key().unwrap(); + let current_user_private_key_id = ctx + .make_private_key(PublicKeyEncryptionAlgorithm::RsaOaepSha1) + .unwrap(); // Get the rotated account keys let rotated_keys = ctx @@ -1027,7 +1030,7 @@ mod tests { .unwrap() .to_der() .unwrap(), - ctx.get_asymmetric_key(current_user_private_key_id) + ctx.get_private_key(current_user_private_key_id) .unwrap() .to_public_key() .to_der() @@ -1041,7 +1044,7 @@ mod tests { PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(decrypted_private_key)).unwrap(); assert_eq!( private_key.to_der().unwrap(), - ctx.get_asymmetric_key(current_user_private_key_id) + ctx.get_private_key(current_user_private_key_id) .unwrap() .to_der() .unwrap() @@ -1072,7 +1075,7 @@ mod tests { .unwrap(); assert_eq!( unwrapped_key.to_der().unwrap(), - ctx.get_asymmetric_key(current_user_private_key_id) + ctx.get_private_key(current_user_private_key_id) .unwrap() .to_public_key() .to_der() diff --git a/crates/bitwarden-crypto/src/store/key_rotation.rs b/crates/bitwarden-crypto/src/store/key_rotation.rs index 8c8af33ba..a39457b5d 100644 --- a/crates/bitwarden-crypto/src/store/key_rotation.rs +++ b/crates/bitwarden-crypto/src/store/key_rotation.rs @@ -49,8 +49,8 @@ pub fn dangerous_get_v2_rotated_account_keys( mod tests { use super::*; use crate::{ - KeyDecryptable, KeyStore, Pkcs8PrivateKeyBytes, PrivateKey, SignatureAlgorithm, SigningKey, - traits::tests::TestIds, + KeyDecryptable, KeyStore, Pkcs8PrivateKeyBytes, PrivateKey, PublicKeyEncryptionAlgorithm, + SignatureAlgorithm, SigningKey, traits::tests::TestIds, }; #[test] @@ -61,7 +61,9 @@ mod tests { // Make the keys let current_user_signing_key_id = ctx.make_signing_key(SignatureAlgorithm::Ed25519).unwrap(); - let current_user_private_key_id = ctx.make_asymmetric_key().unwrap(); + let current_user_private_key_id = ctx + .make_private_key(PublicKeyEncryptionAlgorithm::RsaOaepSha1) + .unwrap(); // Get the rotated account keys let rotated_keys = dangerous_get_v2_rotated_account_keys( @@ -74,7 +76,7 @@ mod tests { // Public/Private key assert_eq!( rotated_keys.public_key, - ctx.get_asymmetric_key(current_user_private_key_id) + ctx.get_private_key(current_user_private_key_id) .unwrap() .to_public_key() .to_der() @@ -88,7 +90,7 @@ mod tests { PrivateKey::from_der(&Pkcs8PrivateKeyBytes::from(decrypted_private_key)).unwrap(); assert_eq!( private_key.to_der().unwrap(), - ctx.get_asymmetric_key(current_user_private_key_id) + ctx.get_private_key(current_user_private_key_id) .unwrap() .to_der() .unwrap() @@ -119,7 +121,7 @@ mod tests { .unwrap(); assert_eq!( unwrapped_key.to_der().unwrap(), - ctx.get_asymmetric_key(current_user_private_key_id) + ctx.get_private_key(current_user_private_key_id) .unwrap() .to_public_key() .to_der() diff --git a/crates/bitwarden-crypto/src/traits/encryptable.rs b/crates/bitwarden-crypto/src/traits/encryptable.rs index ebce60949..06c374589 100644 --- a/crates/bitwarden-crypto/src/traits/encryptable.rs +++ b/crates/bitwarden-crypto/src/traits/encryptable.rs @@ -184,7 +184,7 @@ mod tests { ctx.persist_symmetric_key(local_key_id, TestSymmKey::A(0)) .unwrap(); #[allow(deprecated)] - ctx.set_asymmetric_key(TestAsymmKey::A(0), asymm_key.clone()) + ctx.set_private_key(TestPrivateKey::A(0), asymm_key.clone()) .unwrap(); drop(ctx); diff --git a/crates/bitwarden-crypto/src/traits/key_id.rs b/crates/bitwarden-crypto/src/traits/key_id.rs index fe26d8d69..4a711bc76 100644 --- a/crates/bitwarden-crypto/src/traits/key_id.rs +++ b/crates/bitwarden-crypto/src/traits/key_id.rs @@ -151,7 +151,7 @@ pub(crate) mod tests { use crate::{ KeyId, LocalId, - traits::tests::{TestAsymmKey, TestSigningKey, TestSymmKey}, + traits::tests::{TestPrivateKey, TestSigningKey, TestSymmKey}, }; #[test] diff --git a/crates/bitwarden-crypto/src/traits/mod.rs b/crates/bitwarden-crypto/src/traits/mod.rs index 54946075d..bffd36601 100644 --- a/crates/bitwarden-crypto/src/traits/mod.rs +++ b/crates/bitwarden-crypto/src/traits/mod.rs @@ -30,8 +30,8 @@ pub(crate) mod tests { C(LocalId), } - #[asymmetric] - pub enum TestAsymmKey { + #[private] + pub enum TestPrivateKey { A(u8), B, #[local] @@ -46,6 +46,6 @@ pub(crate) mod tests { C(LocalId), } - pub TestIds => TestSymmKey, TestAsymmKey, TestSigningKey; + pub TestIds => TestSymmKey, TestPrivateKey, TestSigningKey; } } From 197d7ad1302d4efb95396d899f750891d8d81f63 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 18 Dec 2025 18:31:41 +0100 Subject: [PATCH 3/4] Fix build --- crates/bitwarden-core/src/key_management/mod.rs | 4 ++-- crates/bitwarden-crypto/src/enc_string/mod.rs | 2 +- crates/bitwarden-crypto/src/keys/public_key_encryption.rs | 4 ++-- crates/bitwarden-crypto/src/store/context.rs | 2 +- crates/bitwarden-crypto/src/traits/encryptable.rs | 4 ++-- crates/bitwarden-crypto/src/traits/key_id.rs | 2 +- crates/memory-testing/src/lib.rs | 2 +- crates/memory-testing/src/main.rs | 8 ++++---- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/bitwarden-core/src/key_management/mod.rs b/crates/bitwarden-core/src/key_management/mod.rs index 2ade2ac4f..2fa7e7d39 100644 --- a/crates/bitwarden-core/src/key_management/mod.rs +++ b/crates/bitwarden-core/src/key_management/mod.rs @@ -2,8 +2,8 @@ //! Any code that needs to interact with the [KeyStore] should use these types. //! //! - [SymmetricKeyId] is used to identify symmetric keys. -//! - [AsymmetricKeyId] is used to identify asymmetric keys. -//! - [KeyIds] is a helper type that combines both symmetric and asymmetric key identifiers. This is +//! - [PrivateKeyId] is used to identify private keys. +//! - [KeyIds] is a helper type that combines both symmetric and private key identifiers. This is //! usually used in the type bounds of [KeyStore], //! [KeyStoreContext](bitwarden_crypto::KeyStoreContext), //! [PrimitiveEncryptable](bitwarden_crypto::PrimitiveEncryptable), diff --git a/crates/bitwarden-crypto/src/enc_string/mod.rs b/crates/bitwarden-crypto/src/enc_string/mod.rs index 7c0821d84..6286bc7d1 100644 --- a/crates/bitwarden-crypto/src/enc_string/mod.rs +++ b/crates/bitwarden-crypto/src/enc_string/mod.rs @@ -4,7 +4,7 @@ //! encrypted string. They are are used together with the [KeyDecryptable][crate::KeyDecryptable] //! and [KeyEncryptable][crate::KeyEncryptable] traits to encrypt and decrypt data using //! [SymmetricCryptoKey][crate::SymmetricCryptoKey] and -//! [AsymmetricCryptoKey][crate::AsymmetricCryptoKey]s. +//! [PrivateKey][crate::PrivateKey]s. mod asymmetric; mod symmetric; diff --git a/crates/bitwarden-crypto/src/keys/public_key_encryption.rs b/crates/bitwarden-crypto/src/keys/public_key_encryption.rs index 77d88f8af..a8a78a2b5 100644 --- a/crates/bitwarden-crypto/src/keys/public_key_encryption.rs +++ b/crates/bitwarden-crypto/src/keys/public_key_encryption.rs @@ -84,7 +84,7 @@ impl zeroize::ZeroizeOnDrop for PrivateKey {} impl CryptoKey for PrivateKey {} impl PrivateKey { - /// Generate a random AsymmetricCryptoKey (RSA-2048). + /// Generate a random PrivateKey (RSA-2048). pub fn make(algorithm: PublicKeyEncryptionAlgorithm) -> Self { Self::make_internal(algorithm, &mut rand::thread_rng()) } @@ -155,7 +155,7 @@ impl PrivateKey { // We manually implement these to make sure we don't print any sensitive data impl std::fmt::Debug for PrivateKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AsymmetricCryptoKey").finish() + f.debug_struct("PrivateKey").finish() } } diff --git a/crates/bitwarden-crypto/src/store/context.rs b/crates/bitwarden-crypto/src/store/context.rs index 72591cd1e..29b738bd3 100644 --- a/crates/bitwarden-crypto/src/store/context.rs +++ b/crates/bitwarden-crypto/src/store/context.rs @@ -578,7 +578,7 @@ impl KeyStoreContext<'_, Ids> { /// Return a reference to an asymmetric (private) key stored in the context. /// /// Deprecated: intended only for internal use and tests. This exposes the underlying - /// `AsymmetricCryptoKey` reference directly and should not be used by external code. Prefer + /// `PrivateKey` reference directly and should not be used by external code. Prefer /// using the public key via `get_public_key` or other higher-level APIs instead. /// /// # Errors diff --git a/crates/bitwarden-crypto/src/traits/encryptable.rs b/crates/bitwarden-crypto/src/traits/encryptable.rs index 06c374589..f70114579 100644 --- a/crates/bitwarden-crypto/src/traits/encryptable.rs +++ b/crates/bitwarden-crypto/src/traits/encryptable.rs @@ -177,14 +177,14 @@ mod tests { fn test_store() -> KeyStore { let store = KeyStore::::default(); - let asymm_key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); + let private_key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1); let mut ctx = store.context_mut(); let local_key_id = ctx.make_symmetric_key(SymmetricKeyAlgorithm::Aes256CbcHmac); ctx.persist_symmetric_key(local_key_id, TestSymmKey::A(0)) .unwrap(); #[allow(deprecated)] - ctx.set_private_key(TestPrivateKey::A(0), asymm_key.clone()) + ctx.set_private_key(TestPrivateKey::A(0), private_key.clone()) .unwrap(); drop(ctx); diff --git a/crates/bitwarden-crypto/src/traits/key_id.rs b/crates/bitwarden-crypto/src/traits/key_id.rs index 4a711bc76..92e8a3170 100644 --- a/crates/bitwarden-crypto/src/traits/key_id.rs +++ b/crates/bitwarden-crypto/src/traits/key_id.rs @@ -13,7 +13,7 @@ use crate::{CryptoKey, PrivateKey, SigningKey, SymmetricCryptoKey}; /// /// To implement it manually, note that you need a few types: /// - One implementing [KeyId] -/// - One implementing [KeyId] +/// - One implementing [KeyId] /// - One implementing [KeyIds] pub trait KeyId: Debug + Clone + Copy + Hash + Eq + PartialEq + Ord + PartialOrd + Send + Sync + 'static diff --git a/crates/memory-testing/src/lib.rs b/crates/memory-testing/src/lib.rs index 8b51a9e73..67465656a 100644 --- a/crates/memory-testing/src/lib.rs +++ b/crates/memory-testing/src/lib.rs @@ -35,7 +35,7 @@ pub enum CaseCommand { SymmetricKey { key: String, }, - AsymmetricKey { + PrivateKey { private_key: String, }, MasterKey { diff --git a/crates/memory-testing/src/main.rs b/crates/memory-testing/src/main.rs index 91bb8638e..d3680b9a6 100644 --- a/crates/memory-testing/src/main.rs +++ b/crates/memory-testing/src/main.rs @@ -20,7 +20,7 @@ fn main() { let cases = memory_testing::load_cases(base_dir); let mut symmetric_keys = Vec::new(); - let mut asymmetric_keys = Vec::new(); + let mut private_keys = Vec::new(); let mut master_keys = Vec::new(); let mut strings = Vec::new(); @@ -30,9 +30,9 @@ fn main() { let key = SymmetricCryptoKey::try_from(key).unwrap(); symmetric_keys.push((key.to_encoded(), key)); } - memory_testing::CaseCommand::AsymmetricKey { private_key } => { + memory_testing::CaseCommand::PrivateKey { private_key } => { let key = bitwarden_crypto::PrivateKey::from_pem(&private_key).unwrap(); - asymmetric_keys.push(key); + private_keys.push(key); } memory_testing::CaseCommand::MasterKey { password, @@ -62,7 +62,7 @@ fn main() { let _ = std::hint::black_box(( test_string, symmetric_keys, - asymmetric_keys, + private_keys, master_keys, strings, )); From f2fdae9419f5d402555f0ea2af5dd9a410d76269 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 18 Dec 2025 18:37:46 +0100 Subject: [PATCH 4/4] Fix tests --- crates/bitwarden-crypto/src/store/mod.rs | 6 +++--- crates/memory-testing/cases.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden-crypto/src/store/mod.rs b/crates/bitwarden-crypto/src/store/mod.rs index 83e188d36..a85e53a55 100644 --- a/crates/bitwarden-crypto/src/store/mod.rs +++ b/crates/bitwarden-crypto/src/store/mod.rs @@ -57,8 +57,8 @@ pub use key_rotation::*; /// #[local] /// Local(LocalId), /// } -/// #[asymmetric] -/// pub enum AsymmKeyId { +/// #[private] +/// pub enum PrivateKeyId { /// UserPrivate, /// #[local] /// Local(LocalId), @@ -69,7 +69,7 @@ pub use key_rotation::*; /// #[local] /// Local(LocalId), /// } -/// pub Ids => SymmKeyId, AsymmKeyId, SigningKeyId; +/// pub Ids => SymmKeyId, PrivateKeyId, SigningKeyId; /// } /// /// // Initialize the store and insert a test key diff --git a/crates/memory-testing/cases.json b/crates/memory-testing/cases.json index 5223d3671..4cd413e3f 100644 --- a/crates/memory-testing/cases.json +++ b/crates/memory-testing/cases.json @@ -17,8 +17,8 @@ ] }, { - "name": "Asymmetric Key", - "asymmetric_key": { + "name": "Private Key", + "private_key": { "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDiTQVuzhdygFz5\nqv14i+XFDGTnDravzUQT1hPKPGUZOUSZ1gwdNgkWqOIaOnR65BHEnL0sp4bnuiYc\nafeK2JAW5Sc8Z7IxBNSuAwhQmuKx3RochMIiuCkI2/p+JvUQoJu6FBNm8OoJ4Cwm\nqqHGZESMfnpQDCuDrB3JdJEdXhtmnl0C48sGjOk3WaBMcgGqn8LbJDUlyu1zdqyv\nb0waJf0iV4PJm2fkUl7+57D/2TkpbCqURVnZK1FFIEg8mr6FzSN1F2pOfktkNYZw\nP7MSNR7o81CkRSCMr7EkIVa+MZYMBx106BMK7FXgWB7nbSpsWKxBk7ZDHkID2fam\nrEcVtrzDAgMBAAECggEBAKwq9OssGGKgjhvUnyrLJHAZ0dqIMyzk+dotkLjX4gKi\nszJmyqiep6N5sStLNbsZMPtoU/RZMCW0VbJgXFhiEp2YkZU/Py5UAoqw++53J+kx\n0d/IkPphKbb3xUec0+1mg5O6GljDCQuiZXS1dIa/WfeZcezclW6Dz9WovY6ePjJ+\n8vEBR1icbNKzyeINd6MtPtpcgQPHtDwHvhPyUDbKDYGbLvjh9nui8h4+ZUlXKuVR\njB0ChxiKV1xJRjkrEVoulOOicd5r597WfB2ghax3pvRZ4MdXemCXm3gQYqPVKach\nvGU+1cPQR/MBJZpxT+EZA97xwtFS3gqwbxJaNFcoE8ECgYEA9OaeYZhQPDo485tI\n1u/Z7L/3PNape9hBQIXoW7+MgcQ5NiWqYh8Jnj43EIYa0wM/ECQINr1Za8Q5e6KR\nJ30FcU+kfyjuQ0jeXdNELGU/fx5XXNg/vV8GevHwxRlwzqZTCg6UExUZzbYEQqd7\nl+wPyETGeua5xCEywA1nX/D101kCgYEA7I6aMFjhEjO71RmzNhqjKJt6DOghoOfQ\nTjhaaanNEhLYSbenFz1mlb21mW67ulmz162saKdIYLxQNJIP8ZPmxh4ummOJI8w9\nClHfo8WuCI2hCjJ19xbQJocSbTA5aJg6lA1IDVZMDbQwsnAByPRGpaLHBT/Q9Bye\nKvCMB+9amXsCgYEAx65yXSkP4sumPBrVHUub6MntERIGRxBgw/drKcPZEMWp0FiN\nwEuGUBxyUWrG3F69QK/gcqGZE6F/LSu0JvptQaKqgXQiMYJsrRvhbkFvsHpQyUcZ\nUZL1ebFjm5HOxPAgrQaN/bEqxOwwNRjSUWEMzUImg3c06JIZCzbinvudtKECgYEA\nkY3JF/iIPI/yglP27lKDlCfeeHSYxI3+oTKRhzSAxx8rUGidenJAXeDGDauR/T7W\npt3pGNfddBBK9Z3uC4Iq3DqUCFE4f/taj7ADAJ1Q0Vh7/28/IJM77ojr8J1cpZwN\nZy2o6PPxhfkagaDjqEeN9Lrs5LD4nEvDkr5CG1vOjmMCgYEAvIBFKRm31NyF8jLi\nCVuPwC5PzrW5iThDmsWTaXFpB3esUsbICO2pEz872oeQS+Em4GO5vXUlpbbFPzup\nPFhA8iMJ8TAvemhvc7oM0OZqpU6p3K4seHf6BkwLxumoA3vDJfovu9RuXVcJVOnf\nDnqOsltgPomWZ7xVfMkm9niL2OA=\n-----END PRIVATE KEY-----" }, "memory_lookups": [