use chacha20poly1305::aead::{Aead, KeyInit}; use chacha20poly1305::{ChaCha20Poly1305, Key, Nonce}; use crate::protocol::ProtocolError; const NONCE_LEN: usize = 12; pub struct SessionCipher { inner: ChaCha20Poly1305, } impl SessionCipher { pub fn new(key_material: &[u8; 32]) -> Self { let key = Key::from_slice(key_material); Self { inner: ChaCha20Poly1305::new(key), } } pub fn encrypt( &self, nonce_counter: u64, plaintext: &[u8], aad: &[u8], ) -> Result, ProtocolError> { let nonce_bytes = nonce_from_counter(nonce_counter); let nonce = Nonce::from_slice(&nonce_bytes); self.inner .encrypt( nonce, chacha20poly1305::aead::Payload { msg: plaintext, aad, }, ) .map_err(|_| ProtocolError::Crypto("aead-encrypt".to_string())) } pub fn decrypt( &self, nonce_counter: u64, ciphertext: &[u8], aad: &[u8], ) -> Result, ProtocolError> { let nonce_bytes = nonce_from_counter(nonce_counter); let nonce = Nonce::from_slice(&nonce_bytes); self.inner .decrypt( nonce, chacha20poly1305::aead::Payload { msg: ciphertext, aad, }, ) .map_err(|_| ProtocolError::Crypto("aead-decrypt".to_string())) } } fn nonce_from_counter(counter: u64) -> [u8; NONCE_LEN] { let mut nonce = [0_u8; NONCE_LEN]; nonce[4..].copy_from_slice(&counter.to_be_bytes()); nonce }