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