commonware_cryptography/handshake/
cipher.rs1use super::error::Error;
3use chacha20poly1305::{
4 aead::{generic_array::typenum::Unsigned, Aead},
5 AeadCore, ChaCha20Poly1305, KeyInit as _,
6};
7use rand_core::CryptoRngCore;
8use std::vec::Vec;
9use zeroize::ZeroizeOnDrop;
10
11pub const CIPHERTEXT_OVERHEAD: usize = <ChaCha20Poly1305 as AeadCore>::TagSize::USIZE;
13
14const NONCE_SIZE_BYTES: usize = <ChaCha20Poly1305 as AeadCore>::NonceSize::USIZE;
16
17struct CounterNonce {
18 inner: u128,
19}
20
21impl ZeroizeOnDrop for CounterNonce {}
23
24impl CounterNonce {
25 pub fn new() -> Self {
27 Self { inner: 0 }
28 }
29
30 pub fn inc(&mut self) -> Result<[u8; 128 / 8], Error> {
33 if self.inner >= 1 << (8 * NONCE_SIZE_BYTES) {
34 return Err(Error::MessageLimitReached);
35 }
36 let out = self.inner.to_le_bytes();
37 self.inner += 1;
38 Ok(out)
39 }
40}
41
42#[derive(ZeroizeOnDrop)]
43pub struct SendCipher {
44 nonce: CounterNonce,
45 inner: ChaCha20Poly1305,
46}
47
48impl SendCipher {
49 pub fn new(mut rng: impl CryptoRngCore) -> Self {
51 let mut key = [0u8; 32];
52 rng.fill_bytes(&mut key[..]);
53 Self {
54 nonce: CounterNonce::new(),
55 inner: ChaCha20Poly1305::new(&key.into()),
56 }
57 }
58
59 pub fn send(&mut self, data: &[u8]) -> Result<Vec<u8>, Error> {
61 self.inner
62 .encrypt((&self.nonce.inc()?[..NONCE_SIZE_BYTES]).into(), data)
63 .map_err(|_| Error::EncryptionFailed)
64 }
65}
66
67#[derive(ZeroizeOnDrop)]
68pub struct RecvCipher {
69 nonce: CounterNonce,
70 inner: ChaCha20Poly1305,
71}
72
73impl RecvCipher {
74 pub fn new(mut rng: impl CryptoRngCore) -> Self {
76 let mut key = [0u8; 32];
77 rng.fill_bytes(&mut key[..]);
78 Self {
79 nonce: CounterNonce::new(),
80 inner: ChaCha20Poly1305::new(&key.into()),
81 }
82 }
83
84 pub fn recv(&mut self, encrypted_data: &[u8]) -> Result<Vec<u8>, Error> {
86 self.inner
87 .decrypt(
88 (&self.nonce.inc()?[..NONCE_SIZE_BYTES]).into(),
89 encrypted_data,
90 )
91 .map_err(|_| Error::DecryptionFailed)
92 }
93}