1use chacha20poly1305::aead::{rand_core::RngCore, OsRng};
2use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, Error as CryptoError, Key, KeyInit, Nonce, Tag, XChaCha20Poly1305, XNonce};
3
4use crate::NETCODE_MAC_BYTES;
5
6pub fn dencrypted_in_place(buffer: &mut [u8], sequence: u64, private_key: &[u8; 32], aad: &[u8]) -> Result<(), CryptoError> {
7 let mut nonce = [0; 12];
8 nonce[4..12].copy_from_slice(&sequence.to_le_bytes());
9 let nonce = Nonce::from(nonce);
10 let (buffer, tag) = buffer.split_at_mut(buffer.len() - NETCODE_MAC_BYTES);
11 let tag = Tag::from_slice(tag);
12
13 let key = Key::from_slice(private_key);
14 let cipher = ChaCha20Poly1305::new(key);
15
16 cipher.decrypt_in_place_detached(&nonce, aad, buffer, tag)
17}
18
19pub fn dencrypted_in_place_xnonce(buffer: &mut [u8], xnonce: &[u8; 24], private_key: &[u8; 32], aad: &[u8]) -> Result<(), CryptoError> {
20 let xnonce = XNonce::from_slice(xnonce);
21 let (buffer, tag) = buffer.split_at_mut(buffer.len() - NETCODE_MAC_BYTES);
22 let tag = Tag::from_slice(tag);
23
24 let key = Key::from_slice(private_key);
25 let cipher = XChaCha20Poly1305::new(key);
26
27 cipher.decrypt_in_place_detached(xnonce, aad, buffer, tag)
28}
29
30pub fn encrypt_in_place(buffer: &mut [u8], sequence: u64, key: &[u8; 32], aad: &[u8]) -> Result<(), CryptoError> {
31 let mut nonce = [0; 12];
32 nonce[4..12].copy_from_slice(&sequence.to_le_bytes());
33 let nonce = Nonce::from(nonce);
34 let (buffer, buffer_tag) = buffer.split_at_mut(buffer.len() - NETCODE_MAC_BYTES);
35
36 let key = Key::from_slice(key);
37 let cipher = ChaCha20Poly1305::new(key);
38 let tag = cipher.encrypt_in_place_detached(&nonce, aad, buffer)?;
39 buffer_tag.copy_from_slice(&tag);
40
41 Ok(())
42}
43
44pub fn encrypt_in_place_xnonce(buffer: &mut [u8], xnonce: &[u8; 24], key: &[u8; 32], aad: &[u8]) -> Result<(), CryptoError> {
45 let (buffer, buffer_tag) = buffer.split_at_mut(buffer.len() - NETCODE_MAC_BYTES);
46
47 let xnonce = XNonce::from_slice(xnonce);
48 let key = Key::from_slice(key);
49 let cipher = XChaCha20Poly1305::new(key);
50 let tag = cipher.encrypt_in_place_detached(xnonce, aad, buffer)?;
51 buffer_tag.copy_from_slice(&tag);
52
53 Ok(())
54}
55
56pub fn generate_random_bytes<const N: usize>() -> [u8; N] {
61 let mut bytes = [0; N];
62 OsRng.fill_bytes(&mut bytes);
63 bytes
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_encrypt_decrypt_in_place() {
72 let key = b"an example very very secret key."; let sequence = 2;
74 let aad = b"test";
75
76 let mut data = b"some packet data".to_vec();
77 let data_len = data.len();
78 data.extend_from_slice(&[0u8; NETCODE_MAC_BYTES]);
79
80 encrypt_in_place(&mut data, sequence, key, aad).unwrap();
81 dencrypted_in_place(&mut data, sequence, key, aad).unwrap();
82 assert_eq!(&data[..data_len], b"some packet data");
83 }
84}