paramiko ssh 客户端主机密钥签名不匹配失败

paramiko ssh client failing in host key signature mismatch

我们有一个 SSH 服务器实现,我们正在使用 Paramiko 客户端来测试它在 diffie-hellman-group-exchange-shaX 的主机密钥签名不匹配方面始终失败。我已经找出签名不匹配的原因,但无法理解是哪一侧服务器或客户端做错了事。以下是不匹配的原因

1.Client 发送 "min || n || max" 到服务器。

2.Server找到最符合客户要求的组,发送 "p || g" 给客户。其中 p 是大素数,g 是生成器 现在问题发生在服务器发送大小大于 1 的生成器时,它以字节数组表示,前面有零加上它前面的长度为(大数字表示)

00 00 00 04 00 00 00 02 其中 04 是生成器长度,02 是它的值。用于主机密钥签名匹配的 H 使用完整的字节缓冲区用于散列的大数字。 H表示为

H = hash(V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K)

现在,当 paramiko 存储生成器时,它会删除前面的零并且不存储长度。
它将 g 转换回字节,并使用 len(g) 将字节缩小的 g 的长度放在前面进行哈希处理 使用以下例程。

def add_string(self, s):
    """                                                                                                                                                                                                                                  
    Add a string to the stream.                                                                                                                                                                                                          

    :param str s: string to add                                                                                                                                                                                                          
    """
    s = asbytes(s)
    self.add_size(len(s))
    self.packet.write(s)

这只是一个字节,所以我们实际上对 g 字节缓冲区进行哈希处理的内容如下 00 00 00 01 02 其中 01 是字符串长度,02 是与服务器 g 缓冲区不同的值,因此签名不匹配

所以我的问题是哪一侧错误地表示了 big nums 的字节缓冲区?

根据 RFC4251:

Blockquote

  mpint
  Represents multiple precision integers in two's complement format,
  stored as a string, 8 bits per byte, MSB first.  Negative numbers
  have the value 1 as the most significant bit of the first byte of
  the data partition.  If the most significant bit would be set for
  a positive number, the number MUST be preceded by a zero byte.
  Unnecessary leading bytes with the value 0 or 255 MUST NOT be
  included.  The value zero MUST be stored as a string with zero
  bytes of data.
  eg: 80(hex)                 00 00 00 02 00 80

因此服务器的操作是错误的,paramiko 删除前面的填充零是正确的。