use std::error::Error;
use chacha20poly1305::{
AeadCore, ChaCha20Poly1305, Nonce,
aead::{Aead, OsRng},
};
pub(crate) enum Encryption {
#[allow(unused)]
Ccp(ChaCha20Poly1305),
}
impl super::PackUnpack for Encryption {
fn pack(&self, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
match self {
Encryption::Ccp(c) => {
let nonce = ChaCha20Poly1305::generate_nonce(&mut OsRng);
let mut result = nonce.to_vec();
result.extend_from_slice(&c.encrypt(&nonce, data).map_err(|_| "Error encrypting")?);
Ok(result)
}
}
}
fn unpack(&self, data: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
match self {
Encryption::Ccp(c) => {
if data.len() < 12 {
return Err("not enough data for the nonce".into());
}
let nonce_block: [u8; 12] = data[..12].try_into()?;
let nonce: Nonce = nonce_block.into();
Ok(c.decrypt(&nonce, &data[12..])
.map_err(|_| "Error decrypting")?)
}
}
}
}
#[cfg(test)]
mod test {
use super::super::PackUnpack;
use super::*;
use chacha20poly1305::KeyInit;
use quickcheck::quickcheck;
#[test]
fn check_encryption_cc20p1305() {
fn check_array(data: Vec<u8>) -> bool {
let k = ChaCha20Poly1305::generate_key(&mut OsRng);
let c = Encryption::Ccp(ChaCha20Poly1305::new(&k));
let packed = c.pack(&data).unwrap();
let unpacked = c.unpack(&packed).unwrap();
data == unpacked
}
quickcheck(check_array as fn(Vec<u8>) -> bool);
}
}