1use chacha20poly1305::{
4 aead::{self, generic_array::typenum::Unsigned, Aead, AeadCore, KeyInit},
5 ChaCha20Poly1305,
6};
7use hkdf::Hkdf;
8use sha2::Sha256;
9
10pub fn aead_encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
16 let c = ChaCha20Poly1305::new(key.into());
17 c.encrypt(&[0; 12].into(), plaintext)
18 .expect("we won't overflow the ChaCha20 block counter")
19}
20
21pub fn aead_decrypt(
31 key: &[u8; 32],
32 size: usize,
33 ciphertext: &[u8],
34) -> Result<Vec<u8>, aead::Error> {
35 if ciphertext.len() != size + <ChaCha20Poly1305 as AeadCore>::TagSize::to_usize() {
36 return Err(aead::Error);
37 }
38
39 let c = ChaCha20Poly1305::new(key.into());
40 c.decrypt(&[0; 12].into(), ciphertext)
41}
42
43pub fn hkdf(salt: &[u8], label: &[u8], ikm: &[u8]) -> [u8; 32] {
49 let mut okm = [0; 32];
50 Hkdf::<Sha256>::new(Some(salt), ikm)
51 .expand(label, &mut okm)
52 .expect("okm is the correct length");
53 okm
54}
55
56#[cfg(test)]
57mod tests {
58 use super::{aead_decrypt, aead_encrypt};
59
60 #[test]
61 fn aead_round_trip() {
62 let key = [14; 32];
63 let plaintext = b"12345678";
64 let encrypted = aead_encrypt(&key, plaintext);
65 let decrypted = aead_decrypt(&key, plaintext.len(), &encrypted).unwrap();
66 assert_eq!(decrypted, plaintext);
67 }
68}