Skip to content

Commit

Permalink
Explore introducing a Decrypted struct
Browse files Browse the repository at this point in the history
  • Loading branch information
Hinton committed Jan 19, 2024
1 parent b174e49 commit 8c869f2
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 13 deletions.
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/bitwarden-crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ subtle = ">=2.5.0, <3.0"
thiserror = ">=1.0.40, <2.0"
uniffi = { version = "=0.25.2", optional = true }
uuid = { version = ">=1.3.3, <2.0", features = ["serde"] }
zeroize = { version = ">=1.7.0, <2.0", features = ["zeroize_derive"] }

[dev-dependencies]
rand_chacha = "0.3.1"
Expand Down
32 changes: 32 additions & 0 deletions crates/bitwarden-crypto/src/decrypted.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use zeroize::{Zeroize, ZeroizeOnDrop};

use crate::CryptoError;

#[derive(Zeroize, ZeroizeOnDrop)]
pub struct Decrypted<V: Zeroize> {
value: V,
}

impl<V: Zeroize> Decrypted<V> {
pub fn new(value: V) -> Self {
Self { value }
}

pub fn expose(&self) -> &V {
&self.value
}
}

impl TryFrom<Decrypted<Vec<u8>>> for Decrypted<String> {
type Error = CryptoError;

fn try_from(v: Decrypted<Vec<u8>>) -> Result<Self, CryptoError> {
let mut str = v.expose().to_owned();

let rtn = String::from_utf8(str).map_err(|_| CryptoError::InvalidUtf8String);

str.zeroize();

rtn.map(Decrypted::new)
}
}
26 changes: 13 additions & 13 deletions crates/bitwarden-crypto/src/enc_string/symmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::Deserialize;
use super::{check_length, from_b64, from_b64_vec, split_enc_string};
use crate::{
error::{CryptoError, EncStringParseError, Result},
KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey,
Decrypted, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey,
};

/// # Encrypted string primitive
Expand Down Expand Up @@ -228,13 +228,13 @@ impl KeyEncryptable<SymmetricCryptoKey, EncString> for &[u8] {
}
}

impl KeyDecryptable<SymmetricCryptoKey, Vec<u8>> for EncString {
fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result<Vec<u8>> {
impl KeyDecryptable<SymmetricCryptoKey, Decrypted<Vec<u8>>> for EncString {
fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result<Decrypted<Vec<u8>>> {
match self {
EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => {
let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?;
let dec = crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, key.key)?;
Ok(dec)
Ok(Decrypted::new(dec))
}
_ => Err(CryptoError::InvalidKey),
}
Expand All @@ -247,10 +247,10 @@ impl KeyEncryptable<SymmetricCryptoKey, EncString> for String {
}
}

impl KeyDecryptable<SymmetricCryptoKey, String> for EncString {
fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result<String> {
let dec: Vec<u8> = self.decrypt_with_key(key)?;
String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String)
impl KeyDecryptable<SymmetricCryptoKey, Decrypted<String>> for EncString {
fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result<Decrypted<String>> {
let dec: Decrypted<Vec<u8>> = self.decrypt_with_key(key)?;
dec.try_into()
}
}

Expand All @@ -269,17 +269,17 @@ impl schemars::JsonSchema for EncString {
#[cfg(test)]
mod tests {
use super::EncString;
use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable};
use crate::{derive_symmetric_key, Decrypted, KeyDecryptable, KeyEncryptable};

#[test]
fn test_enc_string_roundtrip() {
let key = derive_symmetric_key("test");

let test_string = "encrypted_test_string".to_string();
let cipher = test_string.clone().encrypt_with_key(&key).unwrap();
let test_string = "encrypted_test_string";
let cipher = test_string.to_owned().encrypt_with_key(&key).unwrap();

let decrypted_str: String = cipher.decrypt_with_key(&key).unwrap();
assert_eq!(decrypted_str, test_string);
let decrypted_str: Decrypted<String> = cipher.decrypt_with_key(&key).unwrap();
assert_eq!(decrypted_str.expose(), test_string);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions crates/bitwarden-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub use util::generate_random_bytes;
mod wordlist;
pub use util::pbkdf2;
pub use wordlist::EFF_LONG_WORD_LIST;
mod decrypted;
pub use decrypted::Decrypted;

#[cfg(feature = "mobile")]
uniffi::setup_scaffolding!();
Expand Down

0 comments on commit 8c869f2

Please sign in to comment.