Skip to content

Commit

Permalink
Implement KeyEncryptable support for Asymmetric keys (#447)
Browse files Browse the repository at this point in the history
  • Loading branch information
dani-garcia authored Jan 12, 2024
1 parent bbc47bb commit 4c91270
Show file tree
Hide file tree
Showing 21 changed files with 276 additions and 124 deletions.
22 changes: 9 additions & 13 deletions crates/bitwarden/src/client/encryption_settings.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
use std::collections::HashMap;

use rsa::RsaPrivateKey;
use uuid::Uuid;
#[cfg(feature = "internal")]
use {
crate::{
client::UserLoginMethod,
crypto::{AsymmEncString, EncString, KeyDecryptable},
error::{CryptoError, Result},
},
rsa::pkcs8::DecodePrivateKey,
use crate::{
client::UserLoginMethod,
crypto::{AsymmEncString, EncString, KeyDecryptable},
error::Result,
};
use uuid::Uuid;

use crate::crypto::SymmetricCryptoKey;
use crate::crypto::{AsymmetricCryptoKey, SymmetricCryptoKey};

pub struct EncryptionSettings {
user_key: SymmetricCryptoKey,
pub(crate) private_key: Option<RsaPrivateKey>,
pub(crate) private_key: Option<AsymmetricCryptoKey>,
org_keys: HashMap<Uuid, SymmetricCryptoKey>,
}

Expand Down Expand Up @@ -61,7 +57,7 @@ impl EncryptionSettings {
) -> Result<Self> {
let private_key = {
let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
Some(rsa::RsaPrivateKey::from_pkcs8_der(&dec).map_err(|_| CryptoError::InvalidKey)?)
Some(AsymmetricCryptoKey::from_der(&dec)?)
};

Ok(EncryptionSettings {
Expand Down Expand Up @@ -96,7 +92,7 @@ impl EncryptionSettings {

// Decrypt the org keys with the private key
for (org_id, org_enc_key) in org_enc_keys {
let dec = org_enc_key.decrypt(private_key)?;
let dec: Vec<u8> = org_enc_key.decrypt_with_key(private_key)?;

let org_key = SymmetricCryptoKey::try_from(dec.as_slice())?;

Expand Down
107 changes: 107 additions & 0 deletions crates/bitwarden/src/crypto/asymmetric_crypto_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use rsa::RsaPrivateKey;

use crate::{
crypto::CryptoKey,
error::{CryptoError, Result},
};

/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString)
pub struct AsymmetricCryptoKey {
pub(in crate::crypto) key: RsaPrivateKey,
}

impl AsymmetricCryptoKey {
pub fn from_pem(pem: &str) -> Result<Self> {
use rsa::pkcs8::DecodePrivateKey;
Ok(Self {
key: rsa::RsaPrivateKey::from_pkcs8_pem(pem).map_err(|_| CryptoError::InvalidKey)?,
})
}

pub fn from_der(der: &[u8]) -> Result<Self> {
use rsa::pkcs8::DecodePrivateKey;
Ok(Self {
key: rsa::RsaPrivateKey::from_pkcs8_der(der).map_err(|_| CryptoError::InvalidKey)?,
})
}

pub fn to_der(&self) -> Result<Vec<u8>> {
use rsa::pkcs8::EncodePrivateKey;
Ok(self
.key
.to_pkcs8_der()
.map_err(|_| CryptoError::InvalidKey)?
.as_bytes()
.to_owned())
}

pub fn to_public_der(&self) -> Result<Vec<u8>> {
use rsa::pkcs8::EncodePublicKey;
Ok(self
.key
.to_public_key()
.to_public_key_der()
.map_err(|_| CryptoError::InvalidKey)?
.as_bytes()
.to_owned())
}
}

impl CryptoKey for AsymmetricCryptoKey {}

// We manually implement these to make sure we don't print any sensitive data
impl std::fmt::Debug for AsymmetricCryptoKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AsymmetricCryptoKey").finish()
}
}

#[cfg(test)]
mod tests {
use base64::{engine::general_purpose::STANDARD, Engine};

use super::AsymmetricCryptoKey;

#[test]
fn test_asymmetric_crypto_key() {
let pem_key_str = "-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDiTQVuzhdygFz5
qv14i+XFDGTnDravzUQT1hPKPGUZOUSZ1gwdNgkWqOIaOnR65BHEnL0sp4bnuiYc
afeK2JAW5Sc8Z7IxBNSuAwhQmuKx3RochMIiuCkI2/p+JvUQoJu6FBNm8OoJ4Cwm
qqHGZESMfnpQDCuDrB3JdJEdXhtmnl0C48sGjOk3WaBMcgGqn8LbJDUlyu1zdqyv
b0waJf0iV4PJm2fkUl7+57D/2TkpbCqURVnZK1FFIEg8mr6FzSN1F2pOfktkNYZw
P7MSNR7o81CkRSCMr7EkIVa+MZYMBx106BMK7FXgWB7nbSpsWKxBk7ZDHkID2fam
rEcVtrzDAgMBAAECggEBAKwq9OssGGKgjhvUnyrLJHAZ0dqIMyzk+dotkLjX4gKi
szJmyqiep6N5sStLNbsZMPtoU/RZMCW0VbJgXFhiEp2YkZU/Py5UAoqw++53J+kx
0d/IkPphKbb3xUec0+1mg5O6GljDCQuiZXS1dIa/WfeZcezclW6Dz9WovY6ePjJ+
8vEBR1icbNKzyeINd6MtPtpcgQPHtDwHvhPyUDbKDYGbLvjh9nui8h4+ZUlXKuVR
jB0ChxiKV1xJRjkrEVoulOOicd5r597WfB2ghax3pvRZ4MdXemCXm3gQYqPVKach
vGU+1cPQR/MBJZpxT+EZA97xwtFS3gqwbxJaNFcoE8ECgYEA9OaeYZhQPDo485tI
1u/Z7L/3PNape9hBQIXoW7+MgcQ5NiWqYh8Jnj43EIYa0wM/ECQINr1Za8Q5e6KR
J30FcU+kfyjuQ0jeXdNELGU/fx5XXNg/vV8GevHwxRlwzqZTCg6UExUZzbYEQqd7
l+wPyETGeua5xCEywA1nX/D101kCgYEA7I6aMFjhEjO71RmzNhqjKJt6DOghoOfQ
TjhaaanNEhLYSbenFz1mlb21mW67ulmz162saKdIYLxQNJIP8ZPmxh4ummOJI8w9
ClHfo8WuCI2hCjJ19xbQJocSbTA5aJg6lA1IDVZMDbQwsnAByPRGpaLHBT/Q9Bye
KvCMB+9amXsCgYEAx65yXSkP4sumPBrVHUub6MntERIGRxBgw/drKcPZEMWp0FiN
wEuGUBxyUWrG3F69QK/gcqGZE6F/LSu0JvptQaKqgXQiMYJsrRvhbkFvsHpQyUcZ
UZL1ebFjm5HOxPAgrQaN/bEqxOwwNRjSUWEMzUImg3c06JIZCzbinvudtKECgYEA
kY3JF/iIPI/yglP27lKDlCfeeHSYxI3+oTKRhzSAxx8rUGidenJAXeDGDauR/T7W
pt3pGNfddBBK9Z3uC4Iq3DqUCFE4f/taj7ADAJ1Q0Vh7/28/IJM77ojr8J1cpZwN
Zy2o6PPxhfkagaDjqEeN9Lrs5LD4nEvDkr5CG1vOjmMCgYEAvIBFKRm31NyF8jLi
CVuPwC5PzrW5iThDmsWTaXFpB3esUsbICO2pEz872oeQS+Em4GO5vXUlpbbFPzup
PFhA8iMJ8TAvemhvc7oM0OZqpU6p3K4seHf6BkwLxumoA3vDJfovu9RuXVcJVOnf
DnqOsltgPomWZ7xVfMkm9niL2OA=
-----END PRIVATE KEY-----";

let der_key_vec = STANDARD.decode("MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDiTQVuzhdygFz5qv14i+XFDGTnDravzUQT1hPKPGUZOUSZ1gwdNgkWqOIaOnR65BHEnL0sp4bnuiYcafeK2JAW5Sc8Z7IxBNSuAwhQmuKx3RochMIiuCkI2/p+JvUQoJu6FBNm8OoJ4CwmqqHGZESMfnpQDCuDrB3JdJEdXhtmnl0C48sGjOk3WaBMcgGqn8LbJDUlyu1zdqyvb0waJf0iV4PJm2fkUl7+57D/2TkpbCqURVnZK1FFIEg8mr6FzSN1F2pOfktkNYZwP7MSNR7o81CkRSCMr7EkIVa+MZYMBx106BMK7FXgWB7nbSpsWKxBk7ZDHkID2famrEcVtrzDAgMBAAECggEBAKwq9OssGGKgjhvUnyrLJHAZ0dqIMyzk+dotkLjX4gKiszJmyqiep6N5sStLNbsZMPtoU/RZMCW0VbJgXFhiEp2YkZU/Py5UAoqw++53J+kx0d/IkPphKbb3xUec0+1mg5O6GljDCQuiZXS1dIa/WfeZcezclW6Dz9WovY6ePjJ+8vEBR1icbNKzyeINd6MtPtpcgQPHtDwHvhPyUDbKDYGbLvjh9nui8h4+ZUlXKuVRjB0ChxiKV1xJRjkrEVoulOOicd5r597WfB2ghax3pvRZ4MdXemCXm3gQYqPVKachvGU+1cPQR/MBJZpxT+EZA97xwtFS3gqwbxJaNFcoE8ECgYEA9OaeYZhQPDo485tI1u/Z7L/3PNape9hBQIXoW7+MgcQ5NiWqYh8Jnj43EIYa0wM/ECQINr1Za8Q5e6KRJ30FcU+kfyjuQ0jeXdNELGU/fx5XXNg/vV8GevHwxRlwzqZTCg6UExUZzbYEQqd7l+wPyETGeua5xCEywA1nX/D101kCgYEA7I6aMFjhEjO71RmzNhqjKJt6DOghoOfQTjhaaanNEhLYSbenFz1mlb21mW67ulmz162saKdIYLxQNJIP8ZPmxh4ummOJI8w9ClHfo8WuCI2hCjJ19xbQJocSbTA5aJg6lA1IDVZMDbQwsnAByPRGpaLHBT/Q9ByeKvCMB+9amXsCgYEAx65yXSkP4sumPBrVHUub6MntERIGRxBgw/drKcPZEMWp0FiNwEuGUBxyUWrG3F69QK/gcqGZE6F/LSu0JvptQaKqgXQiMYJsrRvhbkFvsHpQyUcZUZL1ebFjm5HOxPAgrQaN/bEqxOwwNRjSUWEMzUImg3c06JIZCzbinvudtKECgYEAkY3JF/iIPI/yglP27lKDlCfeeHSYxI3+oTKRhzSAxx8rUGidenJAXeDGDauR/T7Wpt3pGNfddBBK9Z3uC4Iq3DqUCFE4f/taj7ADAJ1Q0Vh7/28/IJM77ojr8J1cpZwNZy2o6PPxhfkagaDjqEeN9Lrs5LD4nEvDkr5CG1vOjmMCgYEAvIBFKRm31NyF8jLiCVuPwC5PzrW5iThDmsWTaXFpB3esUsbICO2pEz872oeQS+Em4GO5vXUlpbbFPzupPFhA8iMJ8TAvemhvc7oM0OZqpU6p3K4seHf6BkwLxumoA3vDJfovu9RuXVcJVOnfDnqOsltgPomWZ7xVfMkm9niL2OA=").unwrap();

// 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(&der_key_vec).unwrap();
assert_eq!(pem_key.key, der_key.key);

// Check that the keys can be converted back to DER
assert_eq!(der_key.to_der().unwrap(), der_key_vec);
assert_eq!(pem_key.to_der().unwrap(), der_key_vec);
}
}
110 changes: 72 additions & 38 deletions crates/bitwarden/src/crypto/enc_string/asymmetric.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use std::{fmt::Display, str::FromStr};

use base64::{engine::general_purpose::STANDARD, Engine};
#[cfg(feature = "internal")]
use rsa::{Oaep, RsaPrivateKey};
use rsa::Oaep;
use serde::Deserialize;

use crate::error::{EncStringParseError, Error, Result};

#[cfg(feature = "internal")]
use crate::error::CryptoError;
use crate::{
crypto::{AsymmetricCryptoKey, KeyDecryptable},
error::{CryptoError, EncStringParseError, Error, Result},
};

use super::{from_b64_vec, split_enc_string};

/// # Encrypted string primitive
///
/// [AsymmEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. They are
/// are used together with the KeyDecryptable and KeyEncryptable traits to encrypt and decrypt
/// data using AsymmetricCryptoKeys.
/// data using [AsymmetricCryptoKey]s.
///
/// The flexibility of the [AsymmEncString] type allows for different encryption algorithms to be used
/// which is represented by the different variants of the enum.
Expand Down Expand Up @@ -100,27 +99,6 @@ impl FromStr for AsymmEncString {
}
}

#[allow(unused)]
impl AsymmEncString {
/// TODO: Convert this to a trait method
#[cfg(feature = "internal")]
pub(crate) fn decrypt(&self, key: &RsaPrivateKey) -> Result<Vec<u8>> {
Ok(match self {
Self::Rsa2048_OaepSha256_B64 { data } => key.decrypt(Oaep::new::<sha2::Sha256>(), data),
Self::Rsa2048_OaepSha1_B64 { data } => key.decrypt(Oaep::new::<sha1::Sha1>(), data),
#[allow(deprecated)]
Self::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac: _ } => {
key.decrypt(Oaep::new::<sha2::Sha256>(), data)
}
#[allow(deprecated)]
Self::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac: _ } => {
key.decrypt(Oaep::new::<sha1::Sha1>(), data)
}
}
.map_err(|_| CryptoError::KeyDecrypt)?)
}
}

impl Display for AsymmEncString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let parts: Vec<&[u8]> = match self {
Expand Down Expand Up @@ -172,6 +150,32 @@ impl AsymmEncString {
}
}

impl KeyDecryptable<AsymmetricCryptoKey, Vec<u8>> for AsymmEncString {
fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result<Vec<u8>> {
use AsymmEncString::*;
Ok(match self {
Rsa2048_OaepSha256_B64 { data } => key.key.decrypt(Oaep::new::<sha2::Sha256>(), data),
Rsa2048_OaepSha1_B64 { data } => key.key.decrypt(Oaep::new::<sha1::Sha1>(), data),
#[allow(deprecated)]
Rsa2048_OaepSha256_HmacSha256_B64 { data, .. } => {
key.key.decrypt(Oaep::new::<sha2::Sha256>(), data)
}
#[allow(deprecated)]
Rsa2048_OaepSha1_HmacSha256_B64 { data, .. } => {
key.key.decrypt(Oaep::new::<sha1::Sha1>(), data)
}
}
.map_err(|_| CryptoError::KeyDecrypt)?)
}
}

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

/// Usually we wouldn't want to expose AsymmEncStrings in the API or the schemas.
/// But during the transition phase we will expose endpoints using the AsymmEncString type.
impl schemars::JsonSchema for AsymmEncString {
Expand All @@ -188,12 +192,7 @@ impl schemars::JsonSchema for AsymmEncString {
mod tests {
use super::AsymmEncString;

#[cfg(feature = "internal")]
#[test]
fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() {
use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey};

let rsa_private_key: &str = "-----BEGIN PRIVATE KEY-----
const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS
8HzYUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2
e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86LnhD56A9FDUfuI0dVnPcrwNv0YJIo9
Expand Down Expand Up @@ -221,15 +220,50 @@ Is3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8+tPVgppLcG0+tMdLjigFQiDUQk2y3
WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz
XKZBokBGnjFnTnKcs7nv/O8=
-----END PRIVATE KEY-----";
let private_key = RsaPrivateKey::from_pkcs8_pem(rsa_private_key).unwrap();

#[cfg(feature = "internal")]
#[test]
fn test_enc_string_rsa2048_oaep_sha256_b64() {
use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable};

let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap();
let enc_str: &str = "3.YFqzW9LL/uLjCnl0RRLtndzGJ1FV27mcwQwGjfJPOVrgCX9nJSUYCCDd0iTIyOZ/zRxG47b6L1Z3qgkEfcxjmrSBq60gijc3E2TBMAg7OCLVcjORZ+i1sOVOudmOPWro6uA8refMrg4lqbieDlbLMzjVEwxfi5WpcL876cD0vYyRwvLO3bzFrsE7x33HHHtZeOPW79RqMn5efsB5Dj9wVheC9Ix9AYDjbo+rjg9qR6guwKmS7k2MSaIQlrDR7yu8LP+ePtiSjx+gszJV5jQGfcx60dtiLQzLS/mUD+RmU7B950Bpx0H7x56lT5yXZbWK5YkoP6qd8B8D2aKbP68Ywg==";
let enc_string: AsymmEncString = enc_str.parse().unwrap();

assert_eq!(enc_string.enc_type(), 3);

let res: String = enc_string.decrypt_with_key(&private_key).unwrap();
assert_eq!(res, "EncryptMe!");
}

#[cfg(feature = "internal")]
#[test]
fn test_enc_string_rsa2048_oaep_sha1_b64() {
use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable};

let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap();
let enc_str: &str = "4.ZheRb3PCfAunyFdQYPfyrFqpuvmln9H9w5nDjt88i5A7ug1XE0LJdQHCIYJl0YOZ1gCOGkhFu/CRY2StiLmT3iRKrrVBbC1+qRMjNNyDvRcFi91LWsmRXhONVSPjywzrJJXglsztDqGkLO93dKXNhuKpcmtBLsvgkphk/aFvxbaOvJ/FHdK/iV0dMGNhc/9tbys8laTdwBlI5xIChpRcrfH+XpSFM88+Bu03uK67N9G6eU1UmET+pISJwJvMuIDMqH+qkT7OOzgL3t6I0H2LDj+CnsumnQmDsvQzDiNfTR0IgjpoE9YH2LvPXVP2wVUkiTwXD9cG/E7XeoiduHyHjw==";
let enc_string: AsymmEncString = enc_str.parse().unwrap();

assert_eq!(enc_string.enc_type(), 4);

let res: String = enc_string.decrypt_with_key(&private_key).unwrap();
assert_eq!(res, "EncryptMe!");
}

#[cfg(feature = "internal")]
#[test]
fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() {
use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable};

let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap();
let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ=";
let enc_string: AsymmEncString = enc_str.parse().unwrap();

assert_eq!(enc_string.enc_type(), 6);

let res = enc_string.decrypt(&private_key).unwrap();

assert_eq!(std::str::from_utf8(&res).unwrap(), "EncryptMe!");
let res: String = enc_string.decrypt_with_key(&private_key).unwrap();
assert_eq!(res, "EncryptMe!");
}

#[test]
Expand Down
8 changes: 4 additions & 4 deletions crates/bitwarden/src/crypto/enc_string/symmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,13 @@ impl EncString {
}

impl LocateKey for EncString {}
impl KeyEncryptable<EncString> for &[u8] {
impl KeyEncryptable<SymmetricCryptoKey, EncString> for &[u8] {
fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result<EncString> {
EncString::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key)
}
}

impl KeyDecryptable<Vec<u8>> for EncString {
impl KeyDecryptable<SymmetricCryptoKey, Vec<u8>> for EncString {
fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result<Vec<u8>> {
match self {
EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => {
Expand All @@ -246,13 +246,13 @@ impl KeyDecryptable<Vec<u8>> for EncString {
}
}

impl KeyEncryptable<EncString> for String {
impl KeyEncryptable<SymmetricCryptoKey, EncString> for String {
fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result<EncString> {
self.as_bytes().encrypt_with_key(key)
}
}

impl KeyDecryptable<String> for EncString {
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.into())
Expand Down
4 changes: 2 additions & 2 deletions crates/bitwarden/src/crypto/encryptable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ pub trait Decryptable<Output> {
fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option<Uuid>) -> Result<Output>;
}

impl<T: KeyEncryptable<Output> + LocateKey, Output> Encryptable<Output> for T {
impl<T: KeyEncryptable<SymmetricCryptoKey, Output> + LocateKey, Output> Encryptable<Output> for T {
fn encrypt(self, enc: &EncryptionSettings, org_id: &Option<Uuid>) -> Result<Output> {
let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?;
self.encrypt_with_key(key)
}
}

impl<T: KeyDecryptable<Output> + LocateKey, Output> Decryptable<Output> for T {
impl<T: KeyDecryptable<SymmetricCryptoKey, Output> + LocateKey, Output> Decryptable<Output> for T {
fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option<Uuid>) -> Result<Output> {
let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?;
self.decrypt_with_key(key)
Expand Down
Loading

0 comments on commit 4c91270

Please sign in to comment.