use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
crypto::{Ciphertext, Decrypter, DecrypterExt, Encrypter, EncrypterExt, SymKey, SymKeyKind},
Result,
};
#[derive(Serialize, Deserialize)]
pub struct Envelope<T> {
key: Ciphertext<SymKey>,
payload: Ciphertext<T>,
}
impl<T: Serialize + DeserializeOwned> Envelope<T> {
pub fn new<E: Encrypter>(plaintext: &T, encrypter: E) -> Result<Envelope<T>> {
let symkey = SymKey::generate(SymKeyKind::default())?;
let payload = symkey.ser_encrypt(plaintext)?;
let key = encrypter.ser_encrypt(&symkey)?;
Ok(Envelope { key, payload })
}
pub fn open<D: Decrypter>(&self, decrypter: D) -> Result<T> {
let symkey = decrypter.ser_decrypt(&self.key)?;
symkey.ser_decrypt(&self.payload)
}
}
#[cfg(test)]
mod tests {
use crate::crypto::{envelope::Envelope, ConcreteCreds};
#[test]
fn encrypt_decrypt() {
let creds = ConcreteCreds::generate().unwrap();
let expected = "We attack at the crack of noon.".to_string();
let envelope = Envelope::new(&expected, &creds).unwrap();
let actual = envelope.open(&creds).unwrap();
assert_eq!(expected, actual);
}
}