Skip to content

Commit

Permalink
[PM-9529] Add support for legacy user keys encrypted as AES-CBC-256-B…
Browse files Browse the repository at this point in the history
…64 (#876)

https://bitwarden.atlassian.net/browse/PM-9529

Add support for legacy user keys encrypted as AES-CBC-256-B64
  • Loading branch information
Hinton authored Jul 5, 2024
1 parent f9fb74c commit 552e626
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 18 deletions.
74 changes: 59 additions & 15 deletions crates/bitwarden-core/src/client/test_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,14 @@ pub struct TestAccount {
///
/// ```sql
/// INSERT INTO vault_dev.dbo.[User] (
/// Id, Name, Email, EmailVerified, MasterPassword,
/// MasterPasswordHint, Culture, SecurityStamp,
/// TwoFactorProviders, TwoFactorRecoveryCode,
/// EquivalentDomains, ExcludedGlobalEquivalentDomains,
/// AccountRevisionDate, [Key], PublicKey,
/// PrivateKey, Premium, PremiumExpirationDate,
/// Storage, MaxStorageGb, Gateway, GatewayCustomerId,
/// GatewaySubscriptionId, LicenseKey,
/// CreationDate, RevisionDate, RenewalReminderDate,
/// Kdf, KdfIterations, ReferenceData,
/// ApiKey, ForcePasswordReset, UsesKeyConnector,
/// FailedLoginCount, LastFailedLoginDate,
/// AvatarColor, KdfMemory, KdfParallelism,
/// LastPasswordChangeDate, LastKdfChangeDate,
/// LastKeyRotationDate, LastEmailChangeDate
/// Id, Name, Email, EmailVerified, MasterPassword, MasterPasswordHint, Culture, SecurityStamp,
/// TwoFactorProviders, TwoFactorRecoveryCode, EquivalentDomains,
/// ExcludedGlobalEquivalentDomains, AccountRevisionDate, [Key], PublicKey, PrivateKey, Premium,
/// PremiumExpirationDate, Storage, MaxStorageGb, Gateway, GatewayCustomerId,
/// GatewaySubscriptionId, LicenseKey, CreationDate, RevisionDate, RenewalReminderDate, Kdf,
/// KdfIterations, ReferenceData, ApiKey, ForcePasswordReset, UsesKeyConnector, FailedLoginCount,
/// LastFailedLoginDate, AvatarColor, KdfMemory, KdfParallelism, LastPasswordChangeDate,
/// LastKdfChangeDate, LastKeyRotationDate, LastEmailChangeDate
/// )
/// VALUES
/// (
Expand Down Expand Up @@ -143,3 +136,54 @@ pub fn test_bitwarden_com_account() -> TestAccount {
}),
}
}

/// ### `[email protected]`
///
/// Account which has a user_key of type `AesCbc256_B64` which is deprecated.
///
/// - Email: `[email protected]`
/// - Password: `asdfasdfasdf`
/// - PBKDF2: `600_000` iterations
///
/// ```sql
/// /// INSERT INTO vault_dev.dbo.[User] (
/// Id, Name, Email, EmailVerified, MasterPassword, MasterPasswordHint, Culture, SecurityStamp,
/// TwoFactorProviders, TwoFactorRecoveryCode, EquivalentDomains,
/// ExcludedGlobalEquivalentDomains, AccountRevisionDate, [Key], PublicKey, PrivateKey, Premium,
/// PremiumExpirationDate, Storage, MaxStorageGb, Gateway, GatewayCustomerId,
/// GatewaySubscriptionId, LicenseKey, CreationDate, RevisionDate, RenewalReminderDate, Kdf,
/// KdfIterations, ReferenceData, ApiKey, ForcePasswordReset, UsesKeyConnector, FailedLoginCount,
/// LastFailedLoginDate, AvatarColor, KdfMemory, KdfParallelism, LastPasswordChangeDate,
/// LastKdfChangeDate, LastKeyRotationDate, LastEmailChangeDate
/// )
/// VALUES
/// (
/// N'764335ba-bb3b-4646-9c19-b1a301229eb2', N'Legacy', N'[email protected]', 1,
/// N'AQAAAAIAAYagAAAAEBPKHRNzY+8XTZGODQaa4hQUW/7qsW73v5O8WmqsS+xplghgtX/qXS1JTHT6PNWUFw==',
/// null, N'en-US', N'a1611dff-b383-4d7f-bb37-18c37507c11e', null, null, null, null,
/// N'2024-07-05 13:27:01.4033333',
/// N'0.8UClLa8IPE1iZT7chy5wzQ==|6PVfHnVk5S3XqEtQemnM5yb4JodxmPkkWzmDRdfyHtjORmvxqlLX40tBJZ+CKxQWmS8tpEB5w39rbgHg/gqs0haGdZG4cPbywsgGzxZ7uNI=',
/// N'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvbVTK0cY7j/9GD4UTIZVywT3vWNIiy5LuI1l9MIKbWh+PyVUB5ySR++Z1tDwx5R87AtXwjQS09j6a4X+uGHW4lRQR3Dngb2CpMutLqFjKk7NYWSj3MU5bKlvsCf2Z59ECJEFqo3eAsHYyrL3CixRsZg3LkQcYT+VT/qOOcI6UkMX50lpma2Cvdf3IAgPf6Enkg/WJ3d7D6aU5YtexTY03uKVbOb2UoO2ZJ29VyYEVEJ+0S6pqe9laeHz/oJ9SI3sRqdEYRmyDsbUWJHRJr7eAVesmiUBU/Ls7t4k/oXjfiJ7K5wqL5yCQ0HkqK8zQhi9wB4u7kHwEa8sDJE+cFQ5bQIDAQAB',
/// N'2.leBIE5u0aQUeXi++JzAnrA==|P8x+hs00RJx7epw+49qVtBhLJxE/JTL5dEHg6kq5pbZLdUY8ZvWK49v0EqgHbv1r298N9+msoO9hmdSIVIAZyycemYDSoc1rX4S1KpS/ZMA/Vd3VLFb+o13Ts62GFQ5ygHKgQZfzjU6jO5P/B/0igzFoxyJDomhW5NBC1P9+e/5qNRZN8loKvAaWc/7XtpRayPQqWx+AgYc2ntb1GF5hRVrW4M47bG5ZKllbJWtQKg2sXIy2lDBbKLRFWF4RFzNVcXQGMoPdWLY0f3uTwUH01dyGmFFMbOvfBEuYqmZyPdd93ve8zuFOEqkj46Ulpq2CVG8NvZARTwsdKl6XB0wGuHFoTsDJT2SJGl67pBBKsVRGxy059QW+9hAIB+emIV0T/7+0rvdeSXZ4AbG+oXGEXFTkHefwJKfeT0MBTAjYKr7ZRLgqvf7n39+nCEJU4l22kp8FmjcWIU7AgNipdGHC+UT2yfOcYlvgBgWDcMXcbVDMyus9105RgcW6PHozUj7yjbohI/A3XWmAFufP6BSnmEFCKoik78X/ry09xwiH2rN4KVXe/k9LpRNB2QBGIVsfgCrkxjeE8r0nA59Rvwrhny1z5BkvMW/N1KrGuafg/IYgegx72gJNuZPZlFu1Vs7HxySHmzYvm3DPV7bzCaAxxNtvZmQquNIEnsDQfjJO76iL1JCtDqNJVzGLHTMTr7S5hkOcydcH3kfKwZdA1ULVd2qu0SwOUEP/ECjU/cS5INy6WPYzNMAe/g2DISpQjNwBb5K17PIiGOR7/Q/A6E8pVnkHiAXuUFr9aLOYN9BWSu5Z+BPHH65na2FDmssix5WV09I2sUBfvdNCjkrUGdYgo8E+vOTn35x9GJHF45uhmgC1yAn/+/RSpORlrSVJ7NNP11dn3htUpSsIy/b7ituAu8Ry5mhicFU8CXJL4NeMlXThUt8P++wxs4wMkBvJ8J9NJAVKbAOA2o+GOdjbh6Ww3IRegkurWh4oL/dFSx0LpaXJuw6HFT/LzticPlSwHtUP11hZ81seMsXmkSZd8IugRFfwpPl7N6PVRWDOKxLf4gPqcnJ11TvfasXy1uolV2vZCPbrbbVzQMPdVwL/OzwfhqsIgQZI8rsDMK5D2EX8MaT8MDfGcsYcVTL9PmuZYLpOUnnHX0A1opAAa9iPw3d+eWB/GAyLvKPnMTUqVNos8HcCktXckCshihA8QuBJOwg3m0j2LPSZ5Jvf8gbXauBmt9I4IlJq0xfpgquYY1WNnO8IcWE4N9W+ASvOr9gnduA6CkDeAlyMUFmdpkeCjGMcsV741bTCPApSQlL3/TOT1cjK3iejWpz0OaVHXyg02hW2fNkOfYfr81GvnLvlHxIg4Prw89gKuWU+kQk82lFQo6QQpqbCbJC2FleurD8tYoSY0srhuioVInffvTxw2NMF7FQEqUcsK9AMKSEiDqzBi35Um/fiE3JL4XZBFw8Xzl7X3ab5nlg8X+xD5uSZY+oxD3sDVXjLaQ5JUoys+MCm0FkUj85l0zT6rvM4QLhU1RDK1U51T9HJhh8hsFJsqL4abRzwEWG7PSi859zN4UsgyuQfmBJv/n7QAFCbrJhVBlGB1TKLZRzvgmKoxTYTG3cJFkjetLcUTwrwC9naxAQRfF4=|ufHf73IzJ707dx44w4fjkuD7tDa50OwmmkxcypAT9uQ=',
/// 0, null, null, null, null, null, null, null, N'2024-07-04 17:38:06.7866667',
/// N'2024-07-05 13:27:01.4033333', null, 0, 600000,
/// N'{"id":null,"initiationPath":"Registration form"}', N'Yi9yvlPzvbOuilU0f0pFYuEuxcDy11',
/// 0, 0, 0, null, null, null, null, null, null, null, N'2024-07-05 13:27:01.4033333'
/// );
/// ```
pub fn test_legacy_user_key_account() -> TestAccount {
TestAccount {
user: InitUserCryptoRequest {
kdf_params: Kdf::PBKDF2 {
iterations: 600_000.try_into().unwrap(),
},
email: "[email protected]".to_owned(),
private_key: "2.leBIE5u0aQUeXi++JzAnrA==|P8x+hs00RJx7epw+49qVtBhLJxE/JTL5dEHg6kq5pbZLdUY8ZvWK49v0EqgHbv1r298N9+msoO9hmdSIVIAZyycemYDSoc1rX4S1KpS/ZMA/Vd3VLFb+o13Ts62GFQ5ygHKgQZfzjU6jO5P/B/0igzFoxyJDomhW5NBC1P9+e/5qNRZN8loKvAaWc/7XtpRayPQqWx+AgYc2ntb1GF5hRVrW4M47bG5ZKllbJWtQKg2sXIy2lDBbKLRFWF4RFzNVcXQGMoPdWLY0f3uTwUH01dyGmFFMbOvfBEuYqmZyPdd93ve8zuFOEqkj46Ulpq2CVG8NvZARTwsdKl6XB0wGuHFoTsDJT2SJGl67pBBKsVRGxy059QW+9hAIB+emIV0T/7+0rvdeSXZ4AbG+oXGEXFTkHefwJKfeT0MBTAjYKr7ZRLgqvf7n39+nCEJU4l22kp8FmjcWIU7AgNipdGHC+UT2yfOcYlvgBgWDcMXcbVDMyus9105RgcW6PHozUj7yjbohI/A3XWmAFufP6BSnmEFCKoik78X/ry09xwiH2rN4KVXe/k9LpRNB2QBGIVsfgCrkxjeE8r0nA59Rvwrhny1z5BkvMW/N1KrGuafg/IYgegx72gJNuZPZlFu1Vs7HxySHmzYvm3DPV7bzCaAxxNtvZmQquNIEnsDQfjJO76iL1JCtDqNJVzGLHTMTr7S5hkOcydcH3kfKwZdA1ULVd2qu0SwOUEP/ECjU/cS5INy6WPYzNMAe/g2DISpQjNwBb5K17PIiGOR7/Q/A6E8pVnkHiAXuUFr9aLOYN9BWSu5Z+BPHH65na2FDmssix5WV09I2sUBfvdNCjkrUGdYgo8E+vOTn35x9GJHF45uhmgC1yAn/+/RSpORlrSVJ7NNP11dn3htUpSsIy/b7ituAu8Ry5mhicFU8CXJL4NeMlXThUt8P++wxs4wMkBvJ8J9NJAVKbAOA2o+GOdjbh6Ww3IRegkurWh4oL/dFSx0LpaXJuw6HFT/LzticPlSwHtUP11hZ81seMsXmkSZd8IugRFfwpPl7N6PVRWDOKxLf4gPqcnJ11TvfasXy1uolV2vZCPbrbbVzQMPdVwL/OzwfhqsIgQZI8rsDMK5D2EX8MaT8MDfGcsYcVTL9PmuZYLpOUnnHX0A1opAAa9iPw3d+eWB/GAyLvKPnMTUqVNos8HcCktXckCshihA8QuBJOwg3m0j2LPSZ5Jvf8gbXauBmt9I4IlJq0xfpgquYY1WNnO8IcWE4N9W+ASvOr9gnduA6CkDeAlyMUFmdpkeCjGMcsV741bTCPApSQlL3/TOT1cjK3iejWpz0OaVHXyg02hW2fNkOfYfr81GvnLvlHxIg4Prw89gKuWU+kQk82lFQo6QQpqbCbJC2FleurD8tYoSY0srhuioVInffvTxw2NMF7FQEqUcsK9AMKSEiDqzBi35Um/fiE3JL4XZBFw8Xzl7X3ab5nlg8X+xD5uSZY+oxD3sDVXjLaQ5JUoys+MCm0FkUj85l0zT6rvM4QLhU1RDK1U51T9HJhh8hsFJsqL4abRzwEWG7PSi859zN4UsgyuQfmBJv/n7QAFCbrJhVBlGB1TKLZRzvgmKoxTYTG3cJFkjetLcUTwrwC9naxAQRfF4=|ufHf73IzJ707dx44w4fjkuD7tDa50OwmmkxcypAT9uQ=".to_owned(),
method: InitUserCryptoMethod::Password {
password: "asdfasdfasdf".to_owned(),
user_key: "0.8UClLa8IPE1iZT7chy5wzQ==|6PVfHnVk5S3XqEtQemnM5yb4JodxmPkkWzmDRdfyHtjORmvxqlLX40tBJZ+CKxQWmS8tpEB5w39rbgHg/gqs0haGdZG4cPbywsgGzxZ7uNI=".to_owned(),
}
},
org: None,
}
}
44 changes: 41 additions & 3 deletions crates/bitwarden-crypto/src/keys/master_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,17 @@ impl MasterKey {

/// Decrypt the users user key
pub fn decrypt_user_key(&self, user_key: EncString) -> Result<SymmetricCryptoKey> {
let stretched_key = stretch_kdf_key(&self.0)?;
let mut dec: Vec<u8> = match user_key {
// Legacy. user_keys were encrypted using `AesCbc256_B64` a long time ago. We've since
// moved to using `AesCbc256_HmacSha256_B64`. However, we still need to support
// decrypting these old keys.
EncString::AesCbc256_B64 { .. } => user_key.decrypt_with_key(&self.0)?,
_ => {
let stretched_key = stretch_kdf_key(&self.0)?;
user_key.decrypt_with_key(&stretched_key)?
}
};

let mut dec: Vec<u8> = user_key.decrypt_with_key(&stretched_key)?;
SymmetricCryptoKey::try_from(dec.as_mut_slice())
}

Expand Down Expand Up @@ -124,7 +132,7 @@ mod tests {
use rand::SeedableRng;

use super::{make_user_key, HashPurpose, Kdf, MasterKey};
use crate::{keys::symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey};
use crate::{keys::symmetric_crypto_key::derive_symmetric_key, EncString, SymmetricCryptoKey};

#[test]
fn test_master_key_derive_pbkdf2() {
Expand Down Expand Up @@ -271,4 +279,34 @@ mod tests {
"Decrypted key doesn't match user key"
);
}

#[test]
fn test_decrypt_user_key_aes_cbc256_b64() {
let password = b"asdfasdfasdf";
let salt = b"[email protected]";
let kdf = Kdf::PBKDF2 {
iterations: NonZeroU32::new(600_000).unwrap(),
};

let master_key = MasterKey::derive(password, salt, &kdf).unwrap();

let user_key: EncString = "0.8UClLa8IPE1iZT7chy5wzQ==|6PVfHnVk5S3XqEtQemnM5yb4JodxmPkkWzmDRdfyHtjORmvxqlLX40tBJZ+CKxQWmS8tpEB5w39rbgHg/gqs0haGdZG4cPbywsgGzxZ7uNI=".parse().unwrap();

let decrypted = master_key.decrypt_user_key(user_key).unwrap();

assert_eq!(
decrypted.key.as_slice(),
[
12, 95, 151, 203, 37, 4, 236, 67, 137, 97, 90, 58, 6, 127, 242, 28, 209, 168, 125,
29, 118, 24, 213, 44, 117, 202, 2, 115, 132, 165, 125, 148
]
);
assert_eq!(
decrypted.mac_key.as_ref().unwrap().as_slice(),
[
186, 215, 234, 137, 24, 169, 227, 29, 218, 57, 180, 237, 73, 91, 189, 51, 253, 26,
17, 52, 226, 4, 134, 75, 194, 208, 178, 133, 128, 224, 140, 167
]
);
}
}

0 comments on commit 552e626

Please sign in to comment.