use crate::dek::DEK;
use crate::encryption::EncryptionStrategy;
use crate::error::encryption::EncryptionError;
use async_trait::async_trait;
#[derive(Debug, Clone)]
pub struct HeldValue {
pub(crate) ciphertext: Vec<u8>,
}
impl HeldValue {
pub fn new(ciphertext: Vec<u8>) -> Self {
Self { ciphertext }
}
pub fn value(&self) -> Vec<u8> {
self.ciphertext.clone()
}
}
#[async_trait]
pub trait ReleaseHeldValue<T> {
async fn release<S: EncryptionStrategy<EncryptionData = ED> + Send + Sync, ED: Send>(
&self,
dek: DEK,
strategy: &S,
encryption_data: ED
) -> Result<T, EncryptionError>;
}
#[allow(non_snake_case)]
pub async fn Held<S: EncryptionStrategy<EncryptionData=ED> + Send, ED: Send>(
val: Vec<u8>,
dek: DEK,
strategy: &S,
encryption_data: ED,
) -> Result<HeldValue, EncryptionError> {
strategy.encrypt(dek, val, encryption_data).await.map(|ciphertext| HeldValue::new(ciphertext))
}
#[async_trait]
impl ReleaseHeldValue<Vec<u8>> for HeldValue {
async fn release<S: EncryptionStrategy<EncryptionData = ED> + Send + Sync, ED: Send>(
&self,
dek: DEK,
strategy: &S,
encryption_data: ED
) -> Result<Vec<u8>, EncryptionError> {
strategy.decrypt(dek, self.ciphertext.clone(), encryption_data).await
}
}
#[async_trait]
impl ReleaseHeldValue<String> for HeldValue {
async fn release<S: EncryptionStrategy<EncryptionData = ED> + Send + Sync, ED: Send>(
&self,
dek: DEK,
strategy: &S,
encryption_data: ED
) -> Result<String, EncryptionError> {
let res = strategy.decrypt(dek, self.ciphertext.clone(), encryption_data).await?;
String::from_utf8(res).map_err(|_|
EncryptionError::new("Error translating response to utf8".to_string())
)
}
}
#[cfg(feature = "serde")]
#[async_trait]
impl ReleaseHeldValue<serde_json::Value> for HeldValue {
async fn release<S: EncryptionStrategy<EncryptionData = ED> + Send + Sync, ED: Send>(
&self,
dek: DEK,
strategy: &S,
encryption_data: ED
) -> Result<serde_json::Value, EncryptionError> {
let res = strategy.decrypt(dek, self.ciphertext.clone(), encryption_data).await?;
serde_json
::from_slice(res.as_slice())
.map_err(|e|
EncryptionError(
format!("Could not convert from slice to json value, Error: {:?}", e)
)
)
}
}