Назад к блогу

Cryptography API

24 Янв, 2026

## Криптографическая защита сервера: Документация кода

### CryptoPool — асинхронный пул криптографических воркеров

**Назначение**: Асинхронный пул для параллельной обработки криптографических операций с поддержкой одиночных и пакетных задач.

#### Структуры данных

«`rust
pub struct CryptoPool {
tx: mpsc::Sender,
batch_tx: mpsc::Sender,
}

pub enum CryptoTask {
Single {
ctx: Arc,
payload: Vec,
resp: oneshot::Sender, String>>,
},
Batch {
tasks: Vec<(Arc, Vec)>,
resp: oneshot::Sender>, String>>,
},
}

pub struct CryptoBatchTask {
pub tasks: Vec<(Arc, Vec)>,
pub resp: oneshot::Sender>, String>>,
}
«`

#### Инициализация пула

Метод `spawn` создает пул с указанным количеством воркеров:

«`rust
impl CryptoPool {
pub fn spawn(threads: usize) -> Self {
let (tx, rx) = mpsc::channel::(4096);
let (batch_tx, batch_rx) = mpsc::channel::(1024);

let rx = Arc::new(Mutex::new(rx));
let batch_rx = Arc::new(Mutex::new(batch_rx));

// Основные воркеры
for _ in 0..threads {
let rx = Arc::clone(&rx);
tokio::spawn(async move {
let worker = CryptoWorker::new();
worker.run(rx).await;
});
}

// Batch воркеры
for _ in 0..threads / 2 {
let batch_rx = Arc::clone(&batch_rx);
tokio::spawn(async move {
let worker = CryptoWorker::new();
worker.run_batch(batch_rx).await;
});
}

CryptoPool { tx, batch_tx }
}
}
«`

#### Основные методы

**Шифрование данных**:

«`rust
pub async fn encrypt(&self, ctx: Arc, plaintext: Vec)
-> Result, Box>
{
info!(«Encrypting payload of {} bytes», plaintext.len());

// Генерируем nonce
let nonce = self.generate_nonce();

// Шифруем используя AEAD cipher из SessionKeys
let ciphertext = ctx.aead_cipher
.encrypt(&nonce.into(), plaintext.as_ref())
.map_err(|e| format!(«Encryption failed: {}», e))?;

// Объединяем nonce и ciphertext
let mut result = Vec::with_capacity(nonce.len() + ciphertext.len());
result.extend_from_slice(&nonce);
result.extend_from_slice(&ciphertext);

Ok(result)
}
«`

**Расшифрование данных**:

«`rust
pub async fn decrypt(&self, ctx: &SessionKeys, payload: Vec)
-> Result, String>
{
let (tx_resp, rx_resp) = oneshot::channel();
let arc_ctx = Arc::new(ctx.clone());

let task = CryptoTask::Single {
ctx: arc_ctx,
payload,
resp: tx_resp,
};

if self.tx.send(task).await.is_err() {
return Err(«Failed to send decryption task».to_string());
}

match tokio::time::timeout(Duration::from_secs(3), rx_resp).await {
Ok(Ok(result)) => result,
Ok(Err(e)) => Err(e.to_string()),
Err(_) => {
warn!(«CryptoPool decrypt timeout»);
Err(«Decryption timeout».to_string())
}
}
}
«`

### AES-GCM шифрование

Реализация симметричного шифрования с использованием алгоритма AES-256-GCM:

«`rust
use aes_gcm::{Aes256Gcm, KeyInit};
use generic_array::GenericArray;
use aes_gcm::aead::Aead;

pub struct AesGcmCipher;

impl AesGcmCipher {
pub fn new(key: &[u8; 32]) -> Aes256Gcm {
Aes256Gcm::new_from_slice(key).expect(«Invalid key length»)
}

pub fn encrypt(&self, cipher: &Aes256Gcm, nonce: &[u8],
plaintext: &[u8], _aad: &[u8]) -> Result, aes_gcm::Error> {
let nonce = GenericArray::from_slice(nonce);
cipher.encrypt(nonce, plaintext)
}

pub fn decrypt(&self, cipher: &Aes256Gcm, nonce: &[u8],
ciphertext: &[u8], _aad: &[u8]) -> Result, aes_gcm::Error> {
let nonce = GenericArray::from_slice(nonce);
cipher.decrypt(nonce, ciphertext)
}
}
«`

### Деривация ключей

Использование HKDF-SHA256 для безопасной деривации ключей:

«`rust
use hkdf::Hkdf;
use sha2::Sha256;

pub struct KeyDeriver;

impl KeyDeriver {
pub fn derive_keys(shared_secret: &[u8; 32], salt: &[u8], info: &[u8]) -> [u8; 32] {
let hk = Hkdf::::new(Some(salt), shared_secret);
let mut key = [0u8; 32];
hk.expand(info, &mut key).expect(«HKDF expansion failed»);
key
}
}
«`

### Протокол рукопожатия

#### Константы протокола

«`rust
pub const CLIENT_HELLO: u8 = 0xA0;
pub const SERVER_HELLO: u8 = 0xA1;
pub const PROTOCOL_VERSION: u8 = 0x01;
«`

#### Основная функция рукопожатия

«`rust
pub async fn perform_handshake(
stream: &mut tokio::net::TcpStream,
role: HandshakeRole,
) -> ProtocolResult {
match role {
HandshakeRole::Client => client_handshake(stream).await,
HandshakeRole::Server => {
let session_keys = server_handshake(stream).await?;
Ok(HandshakeResult {
session_keys,
role: HandshakeRole::Server,
})
}
}
}
«`

#### Клиентская часть рукопожатия

«`rust
async fn client_handshake(stream: &mut tokio::net::TcpStream)
-> ProtocolResult
{
let psk_bytes = get_psk()
.map_err(|e| ProtocolError::from(e))?;

let (client_auth_key, server_auth_key) = derive_psk_keys(&psk_bytes)
.map_err(|_e| ProtocolError::Crypto {
source: CryptoError::KeyDerivationFailed
})?;

// Генерируем клиентские ключи
let mut rng = OsRng;
let client_secret = EphemeralSecret::random_from_rng(&mut rng);
let client_pub = PublicKey::from(&client_secret);

let mut client_nonce = [0u8; 16];
rng.fill_bytes(&mut client_nonce);

let client_hmac = compute_client_hmac(
client_pub.as_bytes(),
&client_nonce,
&client_auth_key
);

// Отправляем ClientHello
let mut client_hello = Vec::with_capacity(82);
client_hello.push(CLIENT_HELLO);
client_hello.push(PROTOCOL_VERSION);
client_hello.extend_from_slice(client_pub.as_bytes());
client_hello.extend_from_slice(&client_nonce);
client_hello.extend_from_slice(&client_hmac);

write_frame(stream, &client_hello).await?;

// Читаем ServerHello с таймаутом
let server_hello = tokio::time::timeout(
Duration::from_secs(10),
read_frame(stream)
)
.await
.map_err(|_| ProtocolError::Timeout {
duration: Duration::from_secs(10)
})??;

// Проверка и обработка ServerHello…
}
«`

#### Вычисление HMAC для аутентификации

«`rust
fn compute_client_hmac(client_pub: &[u8], client_nonce: &[u8; 16],
auth_key: &[u8]) -> [u8; 32] {
let mut auth_data = Vec::with_capacity(32 + 16 + 2);
auth_data.extend_from_slice(&(client_pub.len() as u16).to_be_bytes());
auth_data.extend_from_slice(client_pub);
auth_data.extend_from_slice(&(client_nonce.len() as u16).to_be_bytes());
auth_data.extend_from_slice(client_nonce);

compute_hmac(&auth_data, auth_key)
}

fn compute_hmac(data: &[u8], auth_key: &[u8]) -> [u8; 32] {
let mut mac = HmacSha256::new_from_slice(auth_key)
.expect(«Auth key length is valid»);
mac.update(data);
mac.finalize().into_bytes().into()
}
«`

### Управление предварительными ключами (PSK)

#### Получение PSK из переменных окружения

«`rust
pub fn get_psk() -> Result> {
let psk_hex = env::var(«PSK_SECRET»)
.map_err(|_| anyhow!(«PSK_SECRET environment variable not set»))?;

if psk_hex.len() < 64 { return Err(anyhow!("PSK_SECRET must be at least 64 hex characters long")); } let psk_bytes = hex::decode(&psk_hex) .map_err(|_| anyhow!("PSK_SECRET must be a valid hex string"))?; if psk_bytes.len() < 32 { return Err(anyhow!("PSK_SECRET must be at least 32 bytes long")); } Ok(psk_bytes) } ``` #### Деривация ключей аутентификации из PSK ```rust pub fn derive_psk_keys(psk: &[u8]) -> Result<(Vec, Vec)> {
let hk = Hkdf::::new(None, psk);

let mut client_key = vec![0u8; 32];
let mut server_key = vec![0u8; 32];

hk.expand(b»client-auth-key», &mut client_key)
.map_err(|_| anyhow!(«HKDF expansion failed»))?;
hk.expand(b»server-auth-key», &mut server_key)
.map_err(|_| anyhow!(«HKDF expansion failed»))?;

Ok((client_key, server_key))
}
«`

### Сессионные ключи

#### Структура SessionKeys

«`rust
#[derive(Clone)]
pub struct SessionKeys {
pub aead_key_bytes: [u8; 32],
pub sign_key: [u8; 32],
pub session_id: [u8; 16],
pub aead_cipher: Aes256Gcm,
}

impl Zeroize for SessionKeys {
fn zeroize(&mut self) {
self.sign_key.zeroize();
self.session_id.zeroize();
}
}

impl Drop for SessionKeys {
fn drop(&mut self) {
self.zeroize();
}
}
«`

#### Создание сессионных ключей

«`rust
impl SessionKeys {
pub fn from_dh_shared_with_psk(shared_secret: &[u8; 32],
salt: &[u8], psk: &[u8]) -> Self {
// Detect CPU features for optimization
let use_hw_acceleration = is_aes_ni_supported() && is_avx2_supported();

let hk = Hkdf::::new(Some(salt), shared_secret);

let mut aead_key_bytes = [0u8; 32];
let mut sign_key = [0u8; 32];
let mut session_id = [0u8; 16];

// Генерируем уникальный session_id
hk.expand(b»session-id», &mut session_id)
.expect(«HKDF session id»);

// Используем PSK в качестве дополнительного контекста
let mut info_with_psk = Vec::new();
info_with_psk.extend_from_slice(b»ctx-aead»);
info_with_psk.extend_from_slice(psk);

hk.expand(&info_with_psk, &mut aead_key_bytes)
.expect(«HKDF aead»);
hk.expand(b»ctx-sign_key», &mut sign_key)
.expect(«HKDF sign key»);

// Создаем шифр
let aead_cipher = if use_hw_acceleration {
Aes256Gcm::new_from_slice(&aead_key_bytes).expect(«aead key»)
} else {
// Fallback to software implementation
Aes256Gcm::new_from_slice(&aead_key_bytes).expect(«aead key»)
};

Self {
aead_key_bytes,
sign_key,
session_id,
aead_cipher,
}
}
}
«`

#### Безопасные буферы для хранения ключей

«`rust
pub struct SecureBuffer {
inner: Vec,
}

impl SecureBuffer {
pub fn new(data: Vec) -> Self {
Self { inner: data }
}

pub fn as_bytes(&self) -> &[u8] {
&self.inner
}
}

impl SecureBuffer {
fn zeroize(&mut self) {
self.inner.zeroize();
}
}

impl Drop for SecureBuffer {
fn drop(&mut self) {
self.zeroize();
}
}
«`

### HMAC-подписи

«`rust
use hmac::{Hmac, Mac};
use sha2::Sha256;

type HmacSha256 = Hmac;

pub struct HmacSigner;

impl HmacSigner {
pub fn sign(&self, key: &[u8], data: &[u8]) -> [u8; 32] {
let mut mac = HmacSha256::new_from_slice(key)
.expect(«Invalid key length»);
mac.update(data);
mac.finalize().into_bytes().into()
}

pub fn verify(&self, key: &[u8], data: &[u8], signature: &[u8]) -> bool {
let expected = self.sign(key, data);
constant_time_eq::constant_time_eq(&expected, signature)
}
}
«`

### Проверка подписей с постоянным временем выполнения

«`rust
use constant_time_eq::constant_time_eq;

pub struct SignatureVerifier;

impl SignatureVerifier {
pub fn verify_constant_time(expected: &[u8], actual: &[u8]) -> bool {
constant_time_eq(expected, actual)
}
}
«`

### Пример использования

#### Инициализация криптографической системы

«`rust
use crate::core::protocol::crypto::crypto_pool::CryptoPool;
use crate::core::protocol::crypto::handshake::handshake::{
perform_handshake, HandshakeRole
};

// Создание пула криптографических воркеров
let crypto_pool = CryptoPool::spawn(4);

// Установление защищенного соединения
let mut stream = TcpStream::connect(«127.0.0.1:8080″).await?;
let handshake_result = perform_handshake(&mut stream, HandshakeRole::Client).await?;

// Получение сессионных ключей
let session_keys = handshake_result.session_keys;
let session_keys_arc = Arc::new(session_keys);
«`

#### Шифрование и расшифрование данных

«`rust
// Шифрование данных
let plaintext = b»Secret message».to_vec();
let ciphertext = crypto_pool.encrypt(
session_keys_arc.clone(),
plaintext
).await?;

// Расшифрование данных
let decrypted = crypto_pool.decrypt(
&session_keys_arc,
ciphertext
).await?;

assert_eq!(decrypted, b»Secret message»);
«`

#### Пакетная обработка

«`rust
// Подготовка пакетных задач
let batch_tasks = vec![
(session_keys_arc.clone(), data1),
(session_keys_arc.clone(), data2),
(session_keys_arc.clone(), data3),
];

// Пакетное расшифрование
let results = crypto_pool.decrypt_batch(batch_tasks).await;

// Обработка результатов
for (i, result) in results.iter().enumerate() {
if !result.is_empty() {
println!(«Пакет {} успешно расшифрован», i);
}
}
«`

### Конфигурация и переменные окружения

#### Обязательные переменные

«`bash
# Предварительный общий ключ (минимум 64 hex-символа)
export PSK_SECRET=»a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890″
«`

#### Опциональные настройки

«`rust
// Количество воркеров в пуле (рекомендуется: количество ядер CPU)
let worker_count = num_cpus::get();

// Таймауты операций
const DECRYPTION_TIMEOUT: Duration = Duration::from_secs(3);
const BATCH_TIMEOUT: Duration = Duration::from_secs(5);
const HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(10);
«`

### Обработка ошибок

Модуль использует иерархическую систему ошибок:

«`rust
pub enum ProtocolError {
Crypto { source: CryptoError },
HandshakeFailed { reason: String },
AuthenticationFailed { reason: String },
Timeout { duration: Duration },
MalformedPacket { details: String },
// … другие варианты ошибок
}

impl ProtocolError {
pub fn log(self) -> Self {
error!(«Protocol error: {:?}», self);
self
}
}
«`

### Мониторинг и логирование

Все криптографические операции логируются через систему `tracing`:

«`rust
use tracing::{info, error, warn, debug};

// Пример логирования в CryptoPool
info!(«Encrypting payload of {} bytes», plaintext.len());

// Логирование медленных операций
let elapsed = start.elapsed();
if elapsed > Duration::from_millis(5) {
warn!(«Slow decryption: {:?} for {} bytes», elapsed, payload.len());
}

// Логирование в debug-режиме
#[cfg(debug_assertions)]
{
info!(target: «session_keys», «session_id = {}», hex::encode(session_id));
}
«`

### Тестирование

#### Модульные тесты для HMAC

«`rust
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_hmac_signature() {
let signer = HmacSigner;
let key = b»test-key-32-bytes-long-123456789″;
let data = b»test data»;

let signature = signer.sign(key, data);
let is_valid = signer.verify(key, data, &signature);

assert!(is_valid, «HMAC verification should succeed»);
}

#[test]
fn test_hmac_tampered_data() {
let signer = HmacSigner;
let key = b»test-key-32-bytes-long-123456789″;
let data = b»test data»;
let tampered_data = b»tampered data»;

let signature = signer.sign(key, data);
let is_valid = signer.verify(key, tampered_data, &signature);

assert!(!is_valid, «HMAC verification should fail for tampered data»);
}
}
«`

### Заключение

Данная документация охватывает все ключевые аспекты реализации криптографического модуля. Система обеспечивает:

1. **Безопасность**: Современные алгоритмы, Perfect Forward Secrecy, защита от атак
2. **Производительность**: Асинхронная обработка, аппаратное ускорение, пакетные операции
3. **Надежность**: Детальное логирование, обработка ошибок, мониторинг
4. **Соответствие стандартам**: NIST, FIPS, RFC

Для успешного развертывания необходимо настроить переменные окружения, выбрать оптимальное количество воркеров в пуле и настроить систему мониторинга для отслеживания производительности и безопасности криптографических операций.