use chacha20poly1305::{
aead::{self, generic_array::typenum::Unsigned, Aead, AeadCore, KeyInit},
ChaCha20Poly1305,
};
use hkdf::Hkdf;
use sha2::Sha256;
pub fn aead_encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
let c = ChaCha20Poly1305::new(key.into());
c.encrypt(&[0; 12].into(), plaintext)
.expect("we won't overflow the ChaCha20 block counter")
}
pub fn aead_decrypt(
key: &[u8; 32],
size: usize,
ciphertext: &[u8],
) -> Result<Vec<u8>, aead::Error> {
if ciphertext.len() != size + <ChaCha20Poly1305 as AeadCore>::TagSize::to_usize() {
return Err(aead::Error);
}
let c = ChaCha20Poly1305::new(key.into());
c.decrypt(&[0; 12].into(), ciphertext)
}
pub fn hkdf(salt: &[u8], label: &[u8], ikm: &[u8]) -> [u8; 32] {
let mut okm = [0; 32];
Hkdf::<Sha256>::new(Some(salt), ikm)
.expand(label, &mut okm)
.expect("okm is the correct length");
okm
}
#[cfg(test)]
mod tests {
use super::{aead_decrypt, aead_encrypt};
#[test]
fn aead_round_trip() {
let key = [14; 32];
let plaintext = b"12345678";
let encrypted = aead_encrypt(&key, plaintext);
let decrypted = aead_decrypt(&key, plaintext.len(), &encrypted).unwrap();
assert_eq!(decrypted, plaintext);
}
}