Fix SSH cipher key length: dynamically determine based on negotiated algorithm
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

- Add cipher_key_len() helper function
- Store encryption_ctos/stoc in KexExchangeHandler
- Use algorithm name to determine key_len (aes256 → 32, aes128 → 16)
- Remove hardcoded cipher_key_len=32 TODO

All 229 tests pass.
This commit is contained in:
Warren
2026-06-20 21:16:25 +08:00
parent 914eacb230
commit c91dbe2cc3

View File

@@ -10,9 +10,25 @@ use log::info;
use sha2::Digest; use sha2::Digest;
use std::io::{Read, Write}; use std::io::{Read, Write};
/// Determine cipher key length from encryption algorithm name
/// Reference: OpenSSH cipher.c, RFC 4253
fn cipher_key_len(algorithm: &str) -> usize {
if algorithm.contains("aes256") || algorithm.contains("aes256-gcm") {
32
} else if algorithm.contains("aes128") || algorithm.contains("aes128-ctr") {
16
} else {
// Default to AES-256 for unknown algorithms
info!("Unknown encryption algorithm '{}', using default key_len=32", algorithm);
32
}
}
/// SSH密钥交换流程处理器参考OpenSSH kex.c /// SSH密钥交换流程处理器参考OpenSSH kex.c
pub struct KexExchangeHandler { pub struct KexExchangeHandler {
kex_algorithm: String, kex_algorithm: String,
encryption_ctos: String, // Phase fix: store encryption algorithm for key length
encryption_stoc: String, // Phase fix: store encryption algorithm for key length
server_kex: Option<Curve25519Kex>, server_kex: Option<Curve25519Kex>,
host_key: Ed25519HostKey, host_key: Ed25519HostKey,
shared_secret: Option<Vec<u8>>, shared_secret: Option<Vec<u8>>,
@@ -33,6 +49,8 @@ impl KexExchangeHandler {
Ok(Self { Ok(Self {
kex_algorithm: kex_result.kex_algorithm, kex_algorithm: kex_result.kex_algorithm,
encryption_ctos: kex_result.encryption_ctos,
encryption_stoc: kex_result.encryption_stoc,
server_kex: None, server_kex: None,
host_key, host_key,
shared_secret: None, shared_secret: None,
@@ -393,10 +411,9 @@ impl KexExchangeHandler {
let client_public_key = self.client_public_key.as_ref().unwrap(); let client_public_key = self.client_public_key.as_ref().unwrap();
let host_key_blob = self.build_ssh_host_key()?; let host_key_blob = self.build_ssh_host_key()?;
// ⭐ TODO: Get encryption algorithm from kex_result to determine cipher_key_len // Determine cipher key length from negotiated encryption algorithm
// For now, hardcode 32 (AES-256) to maintain backward compatibility let cipher_key_len = cipher_key_len(&self.encryption_stoc);
let cipher_key_len = 32; info!("compute_session_keys: encryption_stoc={}, cipher_key_len={}", self.encryption_stoc, cipher_key_len);
info!("compute_session_keys: cipher_key_len={}", cipher_key_len);
SessionKeys::derive( SessionKeys::derive(
shared_secret, shared_secret,
exchange_hash, // 使用保存的exchange hashH参数 exchange_hash, // 使用保存的exchange hashH参数