use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, KeyInit, Nonce}; use crate::{Error, Result}; const HASH: &[u8] = &[]; struct Key { k: chacha20poly1305::Key, n: u64, } pub struct Transport { encrypt: Key, decrypt: Key, } fn nonce(n: u64) -> Nonce { let mut nonce = [0u8; 12]; nonce[4..].copy_from_slice(&n.to_le_bytes()); Nonce::from(nonce) } impl Transport { pub fn new(encrypt: chacha20poly1305::Key, decrypt: chacha20poly1305::Key) -> Self { Self { encrypt: Key { k: encrypt, n: 0 }, decrypt: Key { k: decrypt, n: 0 }, } } pub fn decrypt(&mut self, data: &mut [u8], tag_data: &[u8]) -> Result<()> { let tag = chacha20poly1305::Tag::from_slice(tag_data); ChaCha20Poly1305::new(&self.decrypt.k) .decrypt_in_place_detached(&nonce(self.decrypt.n), HASH, data, tag) .map_err(|_| Error::ChaCha20Poly1305)?; self.decrypt.n = self.decrypt.n.checked_add(1).ok_or(Error::ExhaustedCounter)?; Ok(()) } pub fn encrypt(&mut self, data: &mut [u8], tag_data: &mut [u8]) -> Result<()> { let tag = ChaCha20Poly1305::new(&self.encrypt.k) .encrypt_in_place_detached(&nonce(self.encrypt.n), HASH, data) .map_err(|_| Error::ChaCha20Poly1305)?; tag_data.copy_from_slice(tag.as_slice()); self.encrypt.n = self.encrypt.n.checked_add(1).ok_or(Error::ExhaustedCounter)?; Ok(()) } }