Implement Phase 1: AES-256-GCM algorithm negotiation and cipher mode setting
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

Performance optimization Phase 1 implementation:
- Add aes-gcm crate dependency (v0.10)
- Add CipherMode enum (AesCtr vs AesGcm)
- Modify KEX algorithm negotiation: add aes256-gcm@openssh.com
- Dynamic cipher mode setting based on KEX result
- Fix HMAC trait conflict with fully-qualified syntax

Strategy: Conservative approach
- Support AES-GCM algorithm negotiation (OpenSSH compatible)
- Dynamic cipher mode setting
- AES-CTR fallback preserved (packet processing unchanged)

Next steps:
- Test OpenSSH client AES-GCM negotiation
- Implement AES-GCM packet processing if needed
- Continue to Phase 4 (parallel encryption)
This commit is contained in:
Warren
2026-06-19 10:10:53 +08:00
parent c59e33f6e4
commit 3575ab7e66
5 changed files with 77 additions and 13 deletions

View File

@@ -3,6 +3,10 @@
use super::crypto::SessionKeys;
use aes::Aes128; // 改为AES-128协商算法是aes128-ctr
use aes_gcm::{
aead::{Aead, KeyInit},
Aes256Gcm, Nonce, // Phase 1: AES-256-GCM AEAD性能优化
};
use anyhow::{anyhow, Result};
use byteorder::{BigEndian, WriteBytesExt};
use cipher::{KeyIvInit, StreamCipher};
@@ -14,20 +18,30 @@ use std::io::Write;
type Aes128Ctr = Ctr128BE<Aes128>; // AES-128-CTR16字节密钥
type HmacSha256 = Hmac<Sha256>;
// Phase 1: AES-256-GCM AEAD32字节密钥 + 12字节nonce + 16字节tag
type Aes256GcmAead = Aes256Gcm; // AES-256-GCMAEAD模式
/// SSH加密通道管理器参考OpenSSH struct sshcipher_ctx
pub struct EncryptionContext {
pub session_id: Vec<u8>, // session identifier (exchange hash)
pub encryption_key_ctos: Vec<u8>, // 客户端→服务器加密密钥
pub encryption_key_stoc: Vec<u8>, // 服务器→客户端加密密钥
pub mac_key_ctos: Vec<u8>, // 客户端→服务器MAC密钥
pub mac_key_stoc: Vec<u8>, // 服务器→客户端MAC密钥
pub mac_key_ctos: Vec<u8>, // 客户端→服务器MAC密钥仅用于AES-CTR
pub mac_key_stoc: Vec<u8>, // 服务器→客户端MAC密钥仅用于AES-CTR
pub iv_ctos: Vec<u8>, // 客户端→服务器IV
pub iv_stoc: Vec<u8>, // 服务器→客户端IV
pub sequence_number_ctos: u32, // 客户端→服务器序列号
pub sequence_number_stoc: u32, // 服务器→客户端序列号
pub cipher_ctos: Option<Aes128Ctr>, // 客户端→服务器cipher实例持久化
pub cipher_stoc: Option<Aes128Ctr>, // 服务器→客户端cipher实例持久化
pub cipher_ctos: Option<Aes128Ctr>, // 客户端→服务器cipher实例持久化AES-CTR
pub cipher_stoc: Option<Aes128Ctr>, // 服务器→客户端cipher实例持久化AES-CTR
pub cipher_mode: CipherMode, // Phase 1: 区分 AES-CTR 和 AES-GCM 模式
}
/// Phase 1: 加密模式选择AES-CTR vs AES-GCM
#[derive(Debug, Clone, PartialEq)]
pub enum CipherMode {
AesCtr, // AES-128-CTR + HMAC-SHA256MtE模式兼容性
AesGcm, // AES-256-GCMAEAD模式性能优化
}
impl Default for EncryptionContext {
@@ -44,6 +58,7 @@ impl Default for EncryptionContext {
sequence_number_stoc: 0,
cipher_ctos: None,
cipher_stoc: None,
cipher_mode: CipherMode::AesCtr, // 默认使用 AES-CTR兼容性
}
}
}
@@ -92,9 +107,42 @@ impl EncryptionContext {
sequence_number_stoc: 0,
cipher_ctos: Some(cipher_ctos), // 持久化cipher实例
cipher_stoc: Some(cipher_stoc), // 持久化cipher实例
cipher_mode: CipherMode::AesCtr, // 默认使用 AES-CTR兼容性
}
}
/// Phase 1: 设置加密模式(根据 KEX 协商结果)
/// 支持 AES-CTR兼容性和 AES-GCM性能优化
pub fn set_cipher_mode(&mut self, mode: CipherMode) -> Result<()> {
info!("Setting cipher mode to: {:?}", mode);
self.cipher_mode = mode.clone();
// 如果切换到 AES-GCM需要重新初始化 cipher使用 32-byte key + 12-byte IV
if mode == CipherMode::AesGcm {
info!("AES-GCM mode: using 32-byte key + 12-byte IV");
// AES-GCM 的 cipher 实例会在 packet 处理时动态创建(因为需要不同的 nonce
// 所以这里只需要清空 AES-CTR cipher
self.cipher_ctos = None;
self.cipher_stoc = None;
} else {
// AES-CTR 模式:重新初始化 AES-CTR cipher
info!("AES-CTR mode: re-initializing with 16-byte key + 16-byte IV");
let key_ctos_array = <[u8; 16]>::try_from(&self.encryption_key_ctos[..16])
.expect("encryption_key_ctos must be 16 bytes");
let iv_ctos_array =
<[u8; 16]>::try_from(&self.iv_ctos[..16]).expect("iv_ctos must be 16 bytes");
self.cipher_ctos = Some(Aes128Ctr::new(&key_ctos_array.into(), &iv_ctos_array.into()));
let key_stoc_array = <[u8; 16]>::try_from(&self.encryption_key_stoc[..16])
.expect("encryption_key_stoc must be 16 bytes");
let iv_stoc_array =
<[u8; 16]>::try_from(&self.iv_stoc[..16]).expect("iv_stoc must be 16 bytes");
self.cipher_stoc = Some(Aes128Ctr::new(&key_stoc_array.into(), &iv_stoc_array.into()));
}
Ok(())
}
/// RFC 4344: Compute AES-CTR IV for a specific packet
/// IV = nonce(8 bytes from derived IV) + sequence_number(8 bytes)
fn compute_ctr_iv(nonce: &[u8], sequence_number: u32) -> Vec<u8> {
@@ -158,8 +206,8 @@ impl EncryptionContext {
mac_key: &[u8],
) -> Result<Vec<u8>> {
// HMAC-SHA256 MAC计算参考OpenSSH mac.c
let mut mac = HmacSha256::new_from_slice(mac_key)?;
// Phase 1: 使用 fully-qualified syntax 避免与 aes_gcm::KeyInit 冲突
let mut mac = <HmacSha256 as hmac::Mac>::new_from_slice(mac_key)?;
// OpenSSH MAC格式sequence_number + data
mac.update(&sequence_number.to_be_bytes());