network_protocol/utils/
crypto.rs

1use chacha20poly1305::{
2    // OsRng and generic_array::GenericArray are unused
3    aead::{Aead, KeyInit},
4    Key,
5    XChaCha20Poly1305,
6    XNonce,
7};
8use getrandom::fill;
9
10use crate::error::{ProtocolError, Result};
11
12pub struct Crypto {
13    cipher: XChaCha20Poly1305,
14}
15
16impl Crypto {
17    pub fn new(key_bytes: &[u8; 32]) -> Self {
18        let key = Key::from_slice(key_bytes);
19        let cipher = XChaCha20Poly1305::new(key);
20        Self { cipher }
21    }
22
23    pub fn encrypt(&self, plaintext: &[u8], nonce: &[u8; 24]) -> Result<Vec<u8>> {
24        let nonce = XNonce::from_slice(nonce);
25        self.cipher
26            .encrypt(nonce, plaintext)
27            .map_err(|_| ProtocolError::EncryptionFailure)
28    }
29
30    pub fn decrypt(&self, ciphertext: &[u8], nonce: &[u8; 24]) -> Result<Vec<u8>> {
31        let nonce = XNonce::from_slice(nonce);
32        self.cipher
33            .decrypt(nonce, ciphertext)
34            .map_err(|_| ProtocolError::DecryptionFailure)
35    }
36
37    /// Generates a secure random 24-byte nonce
38    #[allow(clippy::expect_used)] // cryptographic RNG failure is unrecoverable
39    pub fn generate_nonce() -> [u8; 24] {
40        let mut nonce = [0u8; 24];
41        fill(&mut nonce).expect("Failed to fill nonce");
42        nonce
43    }
44}