docs [AI]
This commit is contained in:
@@ -1,11 +1,31 @@
|
||||
//! Потоковое AEAD-шифрование ChaCha20-Poly1305.
|
||||
//!
|
||||
//! Это «горячий путь» крипто-блока: через него проходит каждый кадр данных.
|
||||
//! Ключевые свойства:
|
||||
//!
|
||||
//! - **Раздельные направления.** [`ChaChaCipher`] держит два независимых потока —
|
||||
//! `tx` (исходящий) и `rx` (входящий), у каждого свой ключ, IV и счётчик nonce.
|
||||
//! - **Детерминированный nonce.** Nonce не передаётся по сети: обе стороны
|
||||
//! синхронно считают `nonce = base_iv XOR counter` (см. [`NonceState`]).
|
||||
//! Счётчики растут строго в ногу, поэтому любой пропуск/повтор кадра ломает
|
||||
//! расшифровку — это и есть встроенная защита целостности потока.
|
||||
//! - **In-place.** Шифр работает прямо в [`BytesMut`] без копий и аллокаций.
|
||||
|
||||
use bytes::BytesMut;
|
||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||
use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, Key, KeyInit, Nonce};
|
||||
|
||||
use crate::crypto::aead::AeadPacker;
|
||||
|
||||
/// Генератор nonce для одного направления.
|
||||
///
|
||||
/// Nonce строится как `base_iv XOR big_endian(counter)` по младшим 8 байтам IV.
|
||||
/// `counter` монотонно растёт на каждый кадр, гарантируя уникальность nonce в
|
||||
/// пределах ключа (повтор nonce при одном ключе фатален для ChaCha20-Poly1305).
|
||||
struct NonceState {
|
||||
/// Счётчик кадров. Должен совпадать у отправителя и получателя по направлению.
|
||||
counter: u64,
|
||||
/// Базовый IV (12 байт), полученный из HKDF; неизменен на всю сессию.
|
||||
base_iv: [u8; 12],
|
||||
}
|
||||
|
||||
@@ -17,6 +37,11 @@ impl NonceState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Возвращает nonce для текущего кадра и инкрементирует счётчик.
|
||||
///
|
||||
/// XOR накладывается на байты `iv[4..12]` (младшие 8 байт 12-байтового IV),
|
||||
/// старшие 4 байта остаются «солью» из IV. После вызова `counter`
|
||||
/// увеличивается, поэтому следующий кадр получит другой nonce.
|
||||
pub fn next_nonce(&mut self) -> Nonce {
|
||||
let mut iv = self.base_iv;
|
||||
let counter_bytes = self.counter.to_be_bytes();
|
||||
@@ -30,6 +55,9 @@ impl NonceState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Однонаправленный шифр: одна пара (ключ, IV) + её счётчик nonce.
|
||||
///
|
||||
/// Реализует [`AeadPacker`]. Используется парами внутри [`ChaChaCipher`].
|
||||
pub struct ChaChaStream {
|
||||
cipher: ChaCha20Poly1305,
|
||||
state: NonceState,
|
||||
@@ -119,12 +147,19 @@ impl AeadPacker for ChaChaStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Двунаправленный шифр сессии: исходящий (`tx`) и входящий (`rx`) потоки.
|
||||
///
|
||||
/// Создаётся «пустым» (нулевые ключи) до завершения хендшейка, затем
|
||||
/// [`set_keys`](ChaChaCipher::set_keys) заряжает реальные ключи из HKDF.
|
||||
pub struct ChaChaCipher {
|
||||
/// Исходящее направление (шифрование того, что отправляем).
|
||||
pub tx: ChaChaStream,
|
||||
/// Входящее направление (расшифровка того, что приняли).
|
||||
pub rx: ChaChaStream,
|
||||
}
|
||||
|
||||
impl ChaChaCipher {
|
||||
/// Создаёт шифр с нулевыми ключами-заглушками (до хендшейка).
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tx: ChaChaStream::new(&[0u8; 32], [0u8; 12]),
|
||||
@@ -132,12 +167,18 @@ impl ChaChaCipher {
|
||||
}
|
||||
}
|
||||
|
||||
/// Заряжает реальные ключи/IV после хендшейка: `w_*` — на запись (tx),
|
||||
/// `r_*` — на чтение (rx). Сбрасывает счётчики nonce в 0 для обоих направлений.
|
||||
pub fn set_keys(&mut self, w_key: [u8; 32], w_iv: [u8; 12], r_key: [u8; 32], r_iv: [u8; 12]) {
|
||||
self.tx = ChaChaStream::new(&w_key, w_iv);
|
||||
self.rx = ChaChaStream::new(&r_key, r_iv);
|
||||
netrunner_logger::debug!("Cipher keys and IVs updated for both directions");
|
||||
}
|
||||
|
||||
/// Разбирает шифр на два независимых потока `(rx, tx)`.
|
||||
///
|
||||
/// Нужно, чтобы отдать чтение и запись в разные задачи tokio (reader/writer),
|
||||
/// не деля шифр под мьютексом — каждое направление владеет своим потоком.
|
||||
pub fn split(self) -> (ChaChaStream, ChaChaStream) {
|
||||
(self.rx, self.tx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user