Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asymmetric encryption support for EncString #222

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/bitwarden/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use {
TwoFactorEmailRequest,
},
client::auth_settings::AuthSettings,
crypto::EncString,
crypto::{AsymmetricEncString, EncString},
platform::{
generate_fingerprint, get_user_api_key, sync, FingerprintRequest, FingerprintResponse,
SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse,
Expand Down Expand Up @@ -244,7 +244,7 @@ impl Client {
#[cfg(feature = "internal")]
pub(crate) fn initialize_org_crypto(
&mut self,
org_keys: Vec<(Uuid, EncString)>,
org_keys: Vec<(Uuid, AsymmetricEncString)>,
) -> Result<&EncryptionSettings> {
let enc = self
.encryption_settings
Expand Down
60 changes: 43 additions & 17 deletions crates/bitwarden/src/client/encryption_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ use std::collections::HashMap;
use rsa::RsaPrivateKey;
use uuid::Uuid;
#[cfg(feature = "internal")]
use {
crate::client::auth_settings::AuthSettings,
rsa::{pkcs8::DecodePrivateKey, Oaep},
};
use {crate::client::auth_settings::AuthSettings, rsa::pkcs8::DecodePrivateKey};

use crate::{
crypto::{encrypt_aes256_hmac, EncString, SymmetricCryptoKey},
crypto::{encrypt_aes256_hmac, AsymmetricEncString, EncString, SymmetricCryptoKey},
error::{CryptoError, Result},
};

Expand Down Expand Up @@ -65,23 +62,15 @@ impl EncryptionSettings {
#[cfg(feature = "internal")]
pub(crate) fn set_org_keys(
&mut self,
org_enc_keys: Vec<(Uuid, EncString)>,
org_enc_keys: Vec<(Uuid, AsymmetricEncString)>,
) -> Result<&mut Self> {
use crate::error::Error;

let private_key = self.private_key.as_ref().ok_or(Error::VaultLocked)?;

// Decrypt the org keys with the private key
for (org_id, org_enc_key) in org_enc_keys {
let data = match org_enc_key {
EncString::Rsa2048_OaepSha1_B64 { data } => data,
_ => return Err(CryptoError::InvalidKey.into()),
};

let dec = private_key
.decrypt(Oaep::new::<sha1::Sha1>(), &data)
.map_err(|_| CryptoError::KeyDecrypt)?;

let dec: Vec<u8> = org_enc_key.decrypt_with_key(private_key)?;
let org_key = SymmetricCryptoKey::try_from(dec.as_slice())?;

self.org_keys.insert(org_id, org_key);
Expand Down Expand Up @@ -122,20 +111,57 @@ impl EncryptionSettings {
let dec = encrypt_aes256_hmac(data, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key)?;
Ok(dec)
}

fn get_asymmetric_key(&self, org_id: &Option<Uuid>) -> Option<&rsa::RsaPrivateKey> {
// TODO: Add key selection here
self.private_key.as_ref()
}

pub(crate) fn decrypt_bytes_asymmetric(
&self,
cipher: &AsymmetricEncString,
org_id: &Option<Uuid>,
) -> Result<Vec<u8>> {
let key = self
.get_asymmetric_key(org_id)
.ok_or(CryptoError::NoKeyForOrg)?;
cipher.decrypt_with_key(key)
}

pub(crate) fn decrypt_asymmetric(
&self,
cipher: &AsymmetricEncString,
org_id: &Option<Uuid>,
) -> Result<String> {
let dec = self.decrypt_bytes_asymmetric(cipher, org_id)?;
String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into())
}

pub(crate) fn encrypt_asymmetric(
&self,
data: &[u8],
org_id: &Option<Uuid>,
) -> Result<AsymmetricEncString> {
let key = self
.get_asymmetric_key(org_id)
.ok_or(CryptoError::NoKeyForOrg)?;

todo!()
}
}

#[cfg(test)]
mod tests {
use super::{EncryptionSettings, SymmetricCryptoKey};
use crate::crypto::{Decryptable, Encryptable};
use crate::crypto::{Decryptable, EncString, Encryptable};

#[test]
fn test_encryption_settings() {
let key = SymmetricCryptoKey::generate("test");
let settings = EncryptionSettings::new_single_key(key);

let test_string = "encrypted_test_string".to_string();
let cipher = test_string.clone().encrypt(&settings, &None).unwrap();
let cipher: EncString = test_string.clone().encrypt(&settings, &None).unwrap();

let decrypted_str = cipher.decrypt(&settings, &None).unwrap();
assert_eq!(decrypted_str, test_string);
Expand Down
6 changes: 4 additions & 2 deletions crates/bitwarden/src/crypto/aes_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use crate::{
error::{CryptoError, Result},
};

use super::EncStringVariants;

pub fn decrypt_aes256(iv: &[u8; 16], data: Vec<u8>, key: GenericArray<u8, U32>) -> Result<Vec<u8>> {
// Decrypt data
let iv = GenericArray::from_slice(iv);
Expand Down Expand Up @@ -42,7 +44,7 @@ pub fn decrypt_aes256_hmac(
pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray<u8, U32>) -> Result<EncString> {
let (iv, data) = encrypt_aes256_internal(data_dec, key);

Ok(EncString::AesCbc256_B64 { iv, data })
Ok(EncStringVariants::AesCbc256_B64 { iv, data }.into())
}

pub fn encrypt_aes256_hmac(
Expand All @@ -53,7 +55,7 @@ pub fn encrypt_aes256_hmac(
let (iv, data) = encrypt_aes256_internal(data_dec, key);
let mac = validate_mac(&mac_key, &iv, &data)?;

Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data })
Ok(EncStringVariants::AesCbc256_HmacSha256_B64 { iv, mac, data }.into())
}

fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray<u8, U32>) -> ([u8; 16], Vec<u8>) {
Expand Down
Loading
Loading