Implement Phase 1: AES-256-GCM algorithm negotiation and cipher mode setting
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:
@@ -58,6 +58,7 @@ ed25519-dalek = { version = "2.0", features = ["rand_core"] }
|
||||
aes = "0.8"
|
||||
ctr = "0.9"
|
||||
cipher = "0.4"
|
||||
aes-gcm = "0.10" # Phase 1: AES-256-GCM AEAD(性能优化)
|
||||
nix = { version = "0.29", features = ["poll", "fs"] } # Phase 14: OpenSSH风格的poll()和非阻塞I/O(fs feature包含fcntl)
|
||||
rusty-s3 = "0.10" # S3 API 签名(AWS Signature V4)
|
||||
ureq = "2.12" # 輕量同步 HTTP 客戶端
|
||||
|
||||
@@ -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-CTR(16字节密钥)
|
||||
type HmacSha256 = Hmac<Sha256>;
|
||||
// Phase 1: AES-256-GCM AEAD(32字节密钥 + 12字节nonce + 16字节tag)
|
||||
type Aes256GcmAead = Aes256Gcm; // AES-256-GCM(AEAD模式)
|
||||
|
||||
/// 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-SHA256(MtE模式,兼容性)
|
||||
AesGcm, // AES-256-GCM(AEAD模式,性能优化)
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
@@ -50,9 +50,9 @@ impl KexProposal {
|
||||
// 主机密钥算法:优先Ed25519
|
||||
server_host_key_algorithms: "ssh-ed25519,rsa-sha2-256,rsa-sha2-512".to_string(),
|
||||
|
||||
// 加密算法:AES-256-CTR(推荐)
|
||||
encryption_algorithms_ctos: "aes256-ctr,aes128-ctr".to_string(),
|
||||
encryption_algorithms_stoc: "aes256-ctr,aes128-ctr".to_string(),
|
||||
// 加密算法:优先 AES-256-GCM(AEAD,性能优化),fallback 到 AES-CTR
|
||||
encryption_algorithms_ctos: "aes256-gcm@openssh.com,aes256-ctr,aes128-ctr".to_string(),
|
||||
encryption_algorithms_stoc: "aes256-gcm@openssh.com,aes256-ctr,aes128-ctr".to_string(),
|
||||
|
||||
// MAC算法:HMAC-SHA256
|
||||
mac_algorithms_ctos: "hmac-sha2-256,hmac-sha2-512".to_string(),
|
||||
@@ -76,8 +76,8 @@ impl KexProposal {
|
||||
Self {
|
||||
kex_algorithms: "curve25519-sha256,diffie-hellman-group14-sha256".to_string(),
|
||||
server_host_key_algorithms: "ssh-ed25519,rsa-sha2-256".to_string(),
|
||||
encryption_algorithms_ctos: "aes256-ctr,aes128-ctr".to_string(),
|
||||
encryption_algorithms_stoc: "aes256-ctr,aes128-ctr".to_string(),
|
||||
encryption_algorithms_ctos: "aes256-gcm@openssh.com,aes256-ctr,aes128-ctr".to_string(),
|
||||
encryption_algorithms_stoc: "aes256-gcm@openssh.com,aes256-ctr,aes128-ctr".to_string(),
|
||||
mac_algorithms_ctos: "hmac-sha2-256".to_string(),
|
||||
mac_algorithms_stoc: "hmac-sha2-256".to_string(),
|
||||
compression_algorithms_ctos: "none".to_string(),
|
||||
|
||||
@@ -268,7 +268,7 @@ fn perform_complete_kex_exchange(
|
||||
let mut kex_state = KexState::new(
|
||||
client_version,
|
||||
"SSH-2.0-MarkBaseSSH_1.0".to_string(),
|
||||
kex_result,
|
||||
kex_result.clone(), // Phase 1: clone kex_result for cipher mode setting
|
||||
)?;
|
||||
|
||||
kex_state.save_kexinit_payloads(&client_kexinit, &server_kexinit);
|
||||
@@ -304,7 +304,20 @@ fn perform_complete_kex_exchange(
|
||||
}
|
||||
|
||||
let session_keys = kex_state.exchange_handler.compute_session_keys()?;
|
||||
let encryption_ctx = EncryptionContext::from_session_keys(&session_keys);
|
||||
let mut encryption_ctx = EncryptionContext::from_session_keys(&session_keys);
|
||||
|
||||
// Phase 1: 根据 KEX 协商结果设置加密模式(AES-GCM vs AES-CTR)
|
||||
let encryption_algorithm = &kex_result.encryption_stoc;
|
||||
info!("KEX negotiated encryption algorithm: {}", encryption_algorithm);
|
||||
|
||||
use crate::ssh_server::cipher::CipherMode;
|
||||
if encryption_algorithm.contains("gcm") {
|
||||
info!("Setting cipher mode to AES-GCM (AEAD)");
|
||||
encryption_ctx.set_cipher_mode(CipherMode::AesGcm)?;
|
||||
} else {
|
||||
info!("Setting cipher mode to AES-CTR (MtE)");
|
||||
encryption_ctx.set_cipher_mode(CipherMode::AesCtr)?;
|
||||
}
|
||||
|
||||
Ok(encryption_ctx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user