Critical fix: KEXINIT exchange hash encoding (prepend SSH_MSG_KEXINIT byte)
OpenSSH kexgex.c source code analysis: - KEXINIT payload stored without SSH_MSG_KEXINIT type byte - Exchange hash prepends SSH_MSG_KEXINIT byte (20) with adjusted length Before fix: - client_kexinit_payload included SSH_MSG_KEXINIT byte - Direct use without prepending After fix: - Remove SSH_MSG_KEXINIT byte from payload - Prepend byte (20) in exchange hash with length+1 - Both kex_exchange.rs and kex_complete.rs updated Testing result: MAC still fails, indicating additional encoding issues Next: Detailed comparison of all exchange hash components
This commit is contained in:
@@ -71,11 +71,19 @@ impl KexState {
|
||||
// V_S: 服务器版本字符串(SSH string格式)
|
||||
write_ssh_string_to_hash(&mut hasher, &self.server_version)?;
|
||||
|
||||
// I_C: 客户端KEXINIT payload(SSH string格式)
|
||||
write_ssh_string_to_hash(&mut hasher, &String::from_utf8_lossy(&self.client_kexinit_payload))?;
|
||||
// OpenSSH kexgex.c: "kexinit messages: fake header: len+SSH2_MSG_KEXINIT"
|
||||
// Remove SSH_MSG_KEXINIT type byte from payloads and prepend it in exchange hash
|
||||
|
||||
// I_S: 服务器KEXINIT payload(SSH string格式)
|
||||
write_ssh_string_to_hash(&mut hasher, &String::from_utf8_lossy(&self.server_kexinit_payload))?;
|
||||
let client_kexinit_without_type = &self.client_kexinit_payload[1..];
|
||||
let server_kexinit_without_type = &self.server_kexinit_payload[1..];
|
||||
|
||||
hasher.update(&((client_kexinit_without_type.len() + 1) as u32).to_be_bytes());
|
||||
hasher.update(&[20]); // SSH_MSG_KEXINIT type byte
|
||||
hasher.update(client_kexinit_without_type);
|
||||
|
||||
hasher.update(&((server_kexinit_without_type.len() + 1) as u32).to_be_bytes());
|
||||
hasher.update(&[20]); // SSH_MSG_KEXINIT type byte
|
||||
hasher.update(server_kexinit_without_type);
|
||||
|
||||
// K_S: 服务器主机密钥blob(SSH string格式)
|
||||
hasher.update(server_host_key_blob);
|
||||
|
||||
Reference in New Issue
Block a user