Skip to content

Commit 977a6b5

Browse files
committed
Move rotation to dangerous_get and clean up types
1 parent 27775ff commit 977a6b5

File tree

7 files changed

+95
-53
lines changed

7 files changed

+95
-53
lines changed

crates/bitwarden-core/src/key_management/crypto.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ use std::collections::HashMap;
99
use base64::{engine::general_purpose::STANDARD, Engine};
1010
use bitwarden_crypto::{
1111
AsymmetricCryptoKey, CoseSerializable, CryptoError, EncString, Kdf, KeyDecryptable,
12-
KeyEncryptable, MasterKey, Pkcs8PrivateKeyBytes, PrimitiveEncryptable, SignatureAlgorithm,
13-
SignedPublicKey, SigningKey, SymmetricCryptoKey, UnsignedSharedKey, UserKey,
12+
KeyEncryptable, MasterKey, Pkcs8PrivateKeyBytes, PrimitiveEncryptable, RotatedUserKeys,
13+
SignatureAlgorithm, SignedPublicKey, SigningKey, SymmetricCryptoKey, UnsignedSharedKey,
14+
UserKey,
1415
};
1516
use bitwarden_error::bitwarden_error;
1617
use schemars::JsonSchema;
@@ -612,6 +613,36 @@ pub fn make_user_signing_keys_for_enrollment(
612613
})
613614
}
614615

616+
/// A rotated set of account keys for a user
617+
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
618+
#[serde(rename_all = "camelCase", deny_unknown_fields)]
619+
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
620+
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
621+
pub struct RotateUserKeysResponse {
622+
/// The verifying key
623+
pub verifying_key: String,
624+
/// Signing key, encrypted with a symmetric key (user key, org key)
625+
pub signing_key: EncString,
626+
/// The user's public key, signed by the signing key
627+
pub signed_public_key: String,
628+
/// The user's public key, without signature
629+
pub public_key: String,
630+
/// The user's private key, encrypted with the user key
631+
pub private_key: EncString,
632+
}
633+
634+
impl From<RotatedUserKeys> for RotateUserKeysResponse {
635+
fn from(rotated: RotatedUserKeys) -> Self {
636+
RotateUserKeysResponse {
637+
verifying_key: Base64String::from(rotated.verifying_key.to_vec()).into(),
638+
signing_key: rotated.signing_key,
639+
signed_public_key: Base64String::from(rotated.signed_public_key.to_vec()).into(),
640+
public_key: Base64String::from(rotated.public_key.to_vec()).into(),
641+
private_key: rotated.private_key,
642+
}
643+
}
644+
}
645+
615646
/// Gets a set of new wrapped account keys for a user, given a new user key.
616647
///
617648
/// In the current implementation, it just re-encrypts any existing keys. This function expects a
@@ -623,12 +654,12 @@ pub fn get_v2_rotated_account_keys(
623654
let key_store = client.internal.get_key_store();
624655
let ctx = key_store.context();
625656

626-
bitwarden_crypto::get_v2_rotated_account_keys(
657+
ctx.dangerous_get_v2_rotated_account_keys(
627658
SymmetricCryptoKey::try_from(user_key)?,
628659
AsymmetricKeyId::UserPrivateKey,
629660
SigningKeyId::UserSigningKey,
630-
&ctx,
631661
)
662+
.map(|rotated| rotated.into())
632663
}
633664

634665
#[cfg(test)]

crates/bitwarden-core/src/key_management/crypto_client.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bitwarden_crypto::{CryptoError, RotateUserKeysResponse};
1+
use bitwarden_crypto::CryptoError;
22
#[cfg(feature = "internal")]
33
use bitwarden_crypto::{EncString, UnsignedSharedKey};
44
#[cfg(feature = "wasm")]
@@ -18,7 +18,9 @@ use crate::key_management::crypto::{
1818
};
1919
use crate::{
2020
client::encryption_settings::EncryptionSettingsError,
21-
key_management::crypto::{get_v2_rotated_account_keys, CryptoClientError},
21+
key_management::crypto::{
22+
get_v2_rotated_account_keys, CryptoClientError, RotateUserKeysResponse,
23+
},
2224
Client,
2325
};
2426

crates/bitwarden-core/src/types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ impl TryInto<Vec<u8>> for Base64String {
2020
}
2121
}
2222

23+
impl Into<String> for Base64String {
24+
fn into(self) -> String {
25+
self.0
26+
}
27+
}
28+
2329
impl From<Vec<u8>> for Base64String {
2430
fn from(val: Vec<u8>) -> Self {
2531
Base64String(STANDARD.encode(val))
Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,39 @@
1-
use base64::{engine::general_purpose::STANDARD, Engine};
2-
use schemars::JsonSchema;
3-
use serde::{Deserialize, Serialize};
4-
#[cfg(feature = "wasm")]
5-
use tsify_next::Tsify;
6-
71
use crate::{
8-
CoseSerializable, CryptoError, EncString, KeyEncryptable, KeyStoreContext, SymmetricCryptoKey,
2+
CoseKeyBytes, CoseSerializable, CoseSign1Bytes, CryptoError, EncString, KeyEncryptable,
3+
KeyStoreContext, SpkiPublicKeyBytes, SymmetricCryptoKey,
94
};
105

116
/// Rotated set of account keys
12-
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
13-
#[serde(rename_all = "camelCase", deny_unknown_fields)]
14-
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
15-
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
16-
pub struct RotateUserKeysResponse {
7+
pub struct RotatedUserKeys {
178
/// The verifying key
18-
verifying_key: String,
9+
pub verifying_key: CoseKeyBytes,
1910
/// Signing key, encrypted with a symmetric key (user key, org key)
20-
signing_key: EncString,
11+
pub signing_key: EncString,
2112
/// The user's public key, signed by the signing key
22-
signed_public_key: String,
23-
// The user's public key, without signature
24-
public_key: String,
25-
// The user's private key, encrypted with the user key
26-
private_key: EncString,
13+
pub signed_public_key: CoseSign1Bytes,
14+
/// The user's public key, without signature
15+
pub public_key: SpkiPublicKeyBytes,
16+
/// The user's private key, encrypted with the user key
17+
pub private_key: EncString,
2718
}
2819

2920
/// Re-encrypts the user's keys with the provided symmetric key for a v2 user.
30-
pub fn get_v2_rotated_account_keys<Ids: crate::KeyIds>(
21+
pub(crate) fn get_v2_rotated_account_keys<Ids: crate::KeyIds>(
3122
new_user_key: SymmetricCryptoKey,
3223
current_user_private_key_id: Ids::Asymmetric,
3324
current_user_signing_key_id: Ids::Signing,
3425
ctx: &KeyStoreContext<Ids>,
35-
) -> Result<RotateUserKeysResponse, CryptoError> {
26+
) -> Result<RotatedUserKeys, CryptoError> {
3627
let signing_key = ctx.get_signing_key(current_user_signing_key_id)?;
3728
let private_key = ctx.get_asymmetric_key(current_user_private_key_id)?;
38-
let signed_public_key: Vec<u8> = ctx
39-
.make_signed_public_key(current_user_private_key_id, current_user_signing_key_id)?
40-
.into();
29+
let signed_public_key =
30+
ctx.make_signed_public_key(current_user_private_key_id, current_user_signing_key_id)?;
4131

42-
Ok(RotateUserKeysResponse {
43-
verifying_key: STANDARD.encode(signing_key.to_verifying_key().to_cose()),
32+
Ok(RotatedUserKeys {
33+
verifying_key: signing_key.to_verifying_key().to_cose(),
4434
signing_key: signing_key.to_cose().encrypt_with_key(&new_user_key)?,
45-
signed_public_key: STANDARD.encode(&signed_public_key),
46-
public_key: STANDARD.encode(private_key.to_public_key().to_der()?),
35+
signed_public_key: signed_public_key.into(),
36+
public_key: private_key.to_public_key().to_der()?,
4737
private_key: private_key.to_der()?.encrypt_with_key(&new_user_key)?,
4838
})
4939
}

crates/bitwarden-crypto/src/keys/signed_public_key.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,23 @@ impl SignedPublicKeyMessage {
7777
#[derive(Clone, Debug)]
7878
pub struct SignedPublicKey(pub(crate) SignedObject);
7979

80-
impl From<SignedPublicKey> for Vec<u8> {
80+
impl From<SignedPublicKey> for CoseSign1Bytes {
8181
fn from(val: SignedPublicKey) -> Self {
82-
val.0.to_cose().to_vec()
82+
val.0.to_cose()
8383
}
8484
}
8585

86-
impl TryFrom<Vec<u8>> for SignedPublicKey {
87-
type Error = EncodingError;
88-
fn try_from(bytes: Vec<u8>) -> Result<Self, EncodingError> {
89-
Ok(SignedPublicKey(SignedObject::from_cose(
90-
&CoseSign1Bytes::from(bytes),
91-
)?))
86+
impl From<SignedPublicKey> for String {
87+
fn from(val: SignedPublicKey) -> Self {
88+
let bytes: CoseSign1Bytes = val.into();
89+
STANDARD.encode(bytes.as_ref())
9290
}
9391
}
9492

95-
impl From<SignedPublicKey> for String {
96-
fn from(val: SignedPublicKey) -> Self {
97-
let bytes: Vec<u8> = val.into();
98-
STANDARD.encode(&bytes)
93+
impl TryFrom<CoseSign1Bytes> for SignedPublicKey {
94+
type Error = EncodingError;
95+
fn try_from(bytes: CoseSign1Bytes) -> Result<Self, EncodingError> {
96+
Ok(SignedPublicKey(SignedObject::from_cose(&bytes)?))
9997
}
10098
}
10199

@@ -130,7 +128,7 @@ impl FromStr for SignedPublicKey {
130128
let bytes = STANDARD
131129
.decode(s)
132130
.map_err(|_| EncodingError::InvalidCborSerialization)?;
133-
Self::try_from(bytes)
131+
Self::try_from(CoseSign1Bytes::from(bytes))
134132
}
135133
}
136134

crates/bitwarden-crypto/src/store/context.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use super::KeyStoreInner;
1010
use crate::{
1111
derive_shareable_key, error::UnsupportedOperation, signing, store::backend::StoreBackend,
1212
AsymmetricCryptoKey, BitwardenLegacyKeyBytes, ContentFormat, CryptoError, EncString, KeyId,
13-
KeyIds, Result, Signature, SignatureAlgorithm, SignedObject, SignedPublicKey,
13+
KeyIds, Result, RotatedUserKeys, Signature, SignatureAlgorithm, SignedObject, SignedPublicKey,
1414
SignedPublicKeyMessage, SigningKey, SymmetricCryptoKey, UnsignedSharedKey,
1515
};
1616

@@ -515,6 +515,21 @@ impl<Ids: KeyIds> KeyStoreContext<'_, Ids> {
515515
) -> Result<(Signature, signing::SerializedMessage)> {
516516
self.get_signing_key(key)?.sign_detached(message, namespace)
517517
}
518+
519+
/// Re-encrypts the user's keys with the provided symmetric key for a v2 user.
520+
pub fn dangerous_get_v2_rotated_account_keys(
521+
&self,
522+
new_user_key: SymmetricCryptoKey,
523+
current_user_private_key_id: Ids::Asymmetric,
524+
current_user_signing_key_id: Ids::Signing,
525+
) -> Result<RotatedUserKeys> {
526+
crate::get_v2_rotated_account_keys(
527+
new_user_key,
528+
current_user_private_key_id,
529+
current_user_signing_key_id,
530+
self,
531+
)
532+
}
518533
}
519534

520535
#[cfg(test)]

crates/bitwarden-wasm-internal/src/pure_crypto.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use std::str::FromStr;
33
use bitwarden_core::key_management::{KeyIds, SymmetricKeyId};
44
use bitwarden_crypto::{
55
AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, CoseKeyBytes,
6-
CoseSerializable, CryptoError, Decryptable, EncString, Kdf, KeyDecryptable, KeyEncryptable,
7-
KeyStore, MasterKey, OctetStreamBytes, Pkcs8PrivateKeyBytes, PrimitiveEncryptable,
8-
SignatureAlgorithm, SignedPublicKey, SigningKey, SpkiPublicKeyBytes, SymmetricCryptoKey,
9-
UnsignedSharedKey, VerifyingKey,
6+
CoseSerializable, CoseSign1Bytes, CryptoError, Decryptable, EncString, Kdf, KeyDecryptable,
7+
KeyEncryptable, KeyStore, MasterKey, OctetStreamBytes, Pkcs8PrivateKeyBytes,
8+
PrimitiveEncryptable, SignatureAlgorithm, SignedPublicKey, SigningKey, SpkiPublicKeyBytes,
9+
SymmetricCryptoKey, UnsignedSharedKey, VerifyingKey,
1010
};
1111
use wasm_bindgen::prelude::*;
1212

@@ -304,7 +304,7 @@ impl PureCrypto {
304304
signed_public_key: Vec<u8>,
305305
verifying_key: Vec<u8>,
306306
) -> Result<Vec<u8>, CryptoError> {
307-
let signed_public_key = SignedPublicKey::try_from(signed_public_key)?;
307+
let signed_public_key = SignedPublicKey::try_from(CoseSign1Bytes::from(signed_public_key))?;
308308
let verifying_key = VerifyingKey::from_cose(&CoseKeyBytes::from(verifying_key))?;
309309
signed_public_key
310310
.verify_and_unwrap(&verifying_key)

0 commit comments

Comments
 (0)