You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SSH服务器ECDH密钥交换回复故障求助:主机密钥签名不匹配

解决PIC SSH服务器ECDH密钥交换的“主机密钥签名不匹配”问题

嘿,我之前在嵌入式MCU上做SSH服务器时,踩过几乎一模一样的ECDH坑!看到你提到的RFC 5656的哈希计算要求,大概率是哈希输入的拼接环节出了细节错误,Putty的错误提示本质就是服务器签名的哈希值和客户端计算的对不上。下面是我总结的几个最容易踩的坑,按优先级排查:

1. 严格对齐RFC 5656的哈希输入拼接规则

先再明确一遍RFC里要求的哈希H的组成(每个元素都是SSH协议定义的字符串类型:4字节大端长度前缀 + 内容字节流):

H = HASH(V_C || V_S || I_C || I_S || K_S || Q_C || Q_S || K)

这里每个部分都不能错,尤其是以下几个细节:

  • V_C/V_S(客户端/服务器标识):必须是握手阶段双方发送的完整版本字符串,比如Putty的V_C是SSH-2.0-Putty_Release_0.78(具体看Putty日志),你的服务器V_S要和你发送的完全一致(必须带SSH-2.0-前缀,不能省略或修改)。我之前就是偷懒把V_S写成了MyPICSSH,少了前缀直接导致哈希完全不匹配。
  • I_C/I_S(KEX_INIT消息):是双方发送的完整KEX_INIT包的字节流(包括消息长度、类型字段,以及里面的所有算法列表),不能只截取算法部分,必须是原始的SSH包内容(按SSH字符串格式拼接)。
  • K_S(服务器主机公钥):必须是SSH标准格式的EC公钥,以nistp256为例,结构是:
    string "ecdsa-sha2-nistp256" || string "nistp256" || string (0x04 + 32字节X + 32字节Y)
    
    别直接把EC公钥的X/Y拼接,必须加上算法标识和曲线名,且公钥是未压缩格式(0x04前缀)。

2. ECDH公钥与共享秘密的字节序/格式问题

  • Q_C/Q_S(ECDH公钥):必须是未压缩的EC点格式(0x04 + X + Y),并且按SSH字符串格式(大端长度前缀+内容)拼接。很多嵌入式EC库默认生成压缩公钥,一定要转成未压缩格式!
  • K(共享秘密):是ECDH计算出的共享点的X坐标(nistp256是32字节),注意要转成大端字节序(PIC是小端架构,这里很容易翻车),再按SSH字符串格式拼接进哈希输入。

3. 哈希算法与签名格式匹配

  • 哈希算法必须和协商的KEX算法对应:比如用ecdh-sha2-nistp256就必须用SHA-256,不能混用SHA-1。
  • 服务器签名格式要正确:用主机私钥对H签名后,要把签名编码成ASN.1 DER格式(结构是0x30 + 总长度 + 0x02 + r长度 + r + 0x02 + s长度 + s),再作为SSH字符串放到KEX回复包里。

实用调试技巧

  • 打开Putty的日志功能(Connection -> SSH -> Logging,选“SSH packets and raw data”),抓下客户端发送的所有包,对比你服务器里收到的V_C、I_C、Q_C是否完全一致。
  • 如果PIC有串口,把拼接好的哈希输入字节流打印出来,用本地工具(比如Python的hashlib)重新计算哈希,对比服务器计算的结果是否一致——这能快速定位是拼接错了还是哈希计算错了。

内容的提问来源于stack exchange,提问作者Networker25

火山引擎 最新活动