如何转换SSH主机密钥以进行验证?

huangapple go评论60阅读模式
英文:

How to convert SSH host keys for validation?

问题

使用 SSH.NET,我正在尝试从我的 SSH 主机(在这种情况下是树莓派)中获取与 Windows SSH 客户端获取的相同的 ed25519rsa 主机密钥,以便我可以将它们与 %USERPROFILE%\.ssh\known_hosts 文件中的内容进行比较。

文档演示了这种技术,但 e.FingerPrint 包含一个 16 元素的字节数组。我希望复制内置的 Win11 SSH 客户端的功能,它以如下方式检索和存储主机密钥:

offsite ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICuy9wsbY7fBFFoB6K0RU/BsISB3mL4PQ3311ta0S/cW
offsite ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAEmXakR9rh5Sokj/PvmyiL/tZtQp7OPbQYb9PdlQjPXELJpBZkFs5gnoqxFj5ysqKnBREY/GpOKkXxdh5dMGGzoir93ypicI7A1VQTd3d8WQdtV1tnP7u9hbAfSqtj+7OGCsi0eMUBYx1fS3XbSC1jKr2MG2ovMCp3kdHtDoGrysP5ai0EXY07ZMmTpxTJbZFtZ8IX3U+ON71KIfZSC6UqlptFyFh1SUmpZXbnsbSr4BDoI8fG0A9Km9BTohWK9ioPSLL530KXz72S4EaBgx0Za1c+TGPqnjAu+s9kc0DeBrwLTEZzfS40xj+sdM4IvPERMBZAPH6cmMutHNWVtIdPyiTi93gCn8oz3D0UX8QT3Yc9Qhx0KLw7AzLajAXSc7zdOebtovZmOejyl4YrYO4Q2rZ3ODTqotFgXGJWNFkg/PoV+Yzy4tILOujDlTHUv3/BkFaj4TSnzgl7NzstdZpNM1R0KBkHlDuM10K9yyLEmNlHSvx8zTZWBTEkzb1FoU=

我尝试遍历 SSH.NET 的 Client.ConnectionInfo.HostKeyAlgorithms 字典,但我不确定从哪里获取一个条目的值调用所需的字节数组:

Dim aData As Byte() = Nothing

For Each oAlgorithm In oClient.ConnectionInfo.HostKeyAlgorithms
  Dim oInstance = oAlgorithm.Value(aData)
End For

这段代码会失败,因为 Func(Of Byte(), KeyHostAlgorithm) 调用需要一个具有元素的实际数组。它也拒绝空数组(以及任何其他数组)。例如:

oAlgorithm.Value({})

请求的长度(4)大于实际读取的字节数(0)。参数名称:length

oAlgorithm.Value({0, 1, 2})

请求的长度(4)大于实际读取的字节数(3)。参数名称:length

oAlgorithm.Value({0, 1, 2, 3})

不支持长度超过 2147483647 的数据。

在这里有什么问题?这个字节数组参数应该是什么,人们应该从哪里获取它?

我还在 Client.HostKeyReceived 事件处理程序中尝试了以下方法:

Dim sHostKey = Convert.ToBase64String(New SHA256Managed().ComputeHash(e.HostKey))

但计算出的 Base64 字符串与我 known_hosts 文件中当前的条目不匹配(请参见上面)。

如何以一种与 known_hosts(特别是 ed25519rsa)中的内容匹配的方式从 SSH 主机检索各种密钥?

--编辑--

我已成功找到要在函数调用中使用的字节数组:

oHandler = Sub(Sender As SshClient, e As HostKeyEventArgs)
             Dim aData As Byte()

             For Each oAlgorithm In Sender.ConnectionInfo.HostKeyAlgorithms
               Dim oInstance = oAlgorithm.Value(e.HostKey)

               If TypeOf oInstance.Key Is Ed25519Key Then
                 aData = DirectCast(oInstance.Key, Ed25519Key).PublicKey
                 Exit For
               End If
             Next
           End Sub

然而,aData 的计算的 Base64 仍然不与 Win11 SSH 客户端的输出相匹配。有谁知道这些值是如何计算出来的?

--编辑--

好的,我离成功更近了。我现在拥有 Windows 供应的 SSH 客户端的 ed25519 的值。它是在对服务器的 HostKey 进行任何哈希处理之前的服务器 HostKey 的 Base64 编码:

Dim sBase64 = Convert.ToBase64String(e.HostKey)
' 返回 AAAAC3NzaC1lZDI1NTE5AAAAICuy9wsbY7fBFFoB6K0RU/BsISB3mL4PQ3311ta0S/cW

现在要尝试获取服务器的 rsa 密钥相同的值。

英文:

Using SSH.NET, I'm trying to get the same ed25519 and rsa host keys from my SSH host (a Raspberry Pi in this case) that the Windows SSH client gets, so that I can compare them to what's in the %USERPROFILE%\.ssh\known_hosts file.

The documentation demonstrates this technique, but e.FingerPrint contains a 16-element byte array. I wish to replicate the functionality of the in-built Win11 SSH client that retrieves and stores the host keys like so:

offsite ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICuy9wsbY7fBFFoB6K0RU/BsISB3mL4PQ3311ta0S/cW
offsite ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAEmXakR9rh5Sokj/PvmyiL/tZtQp7OPbQYb9PdlQjPXELJpBZkFs5gnoqxFj5ysqKnBREY/GpOKkXxdh5dMGGzoir93ypicI7A1VQTd3d8WQdtV1tnP7u9hbAfSqtj+7OGCsi0eMUBYx1fS3XbSC1jKr2MG2ovMCp3kdHtDoGrysP5ai0EXY07ZMmTpxTJbZFtZ8IX3U+ON71KIfZSC6UqlptFyFh1SUmpZXbnsbSr4BDoI8fG0A9Km9BTohWK9ioPSLL530KXz72S4EaBgx0Za1c+TGPqnjAu+s9kc0DeBrwLTEZzfS40xj+sdM4IvPERMBZAPH6cmMutHNWVtIdPyiTi93gCn8oz3D0UX8QT3Yc9Qhx0KLw7AzLajAXSc7zdOebtovZmOejyl4YrYO4Q2rZ3ODTqotFgXGJWNFkg/PoV+Yzy4tILOujDlTHUv3/BkFaj4TSnzgl7NzstdZpNM1R0KBkHlDuM10K9yyLEmNlHSvx8zTZWBTEkzb1FoU=

I've tried looping through SSH.NET's Client.ConnectionInfo.HostKeyAlgorithms dictionary, but I'm not sure where to get the byte array that's required by an entry's value invocation:

Dim aData As Byte() = Nothing

For Each oAlgorithm In oClient.ConnectionInfo.HostKeyAlgorithms
  Dim oInstance = oAlgorithm.Value(aData)
End For

That code fails, as the Func(Of Byte(), KeyHostAlgorithm) invocation requires an actual array with elements. It also rejects an empty array (and any other array, for that matter). For example:

oAlgorithm.Value({})

> The requested length (4) is greater than the actual number of bytes read (0).Parameter name: length

oAlgorithm.Value({0, 1, 2})

> The requested length (4) is greater than the actual number of bytes read (3).Parameter name: length

oAlgorithm.Value({0, 1, 2, 3})

> Data longer than 2147483647 is not supported.

What gives here? What's that byte array parameter supposed to be and where does one get it?

I also tried this in the Client.HostKeyReceived event handler:

Dim sHostKey = Convert.ToBase64String(New SHA256Managed().ComputeHash(e.HostKey))

But that calculated Base64 string differs from the entry currently in my known_hosts file for that host (see above).

How do I retrieve the various keys from the SSH host, in a way that matches what's in known_hosts (ed25519 and rsa in particular)?

--EDIT--

I've succeeded in discovering the byte array to be used in the function invocation:

oHandler = Sub(Sender As SshClient, e As HostKeyEventArgs)
             Dim aData As Byte()

             For Each oAlgorithm In Sender.ConnectionInfo.HostKeyAlgorithms
               Dim oInstance = oAlgorithm.Value(e.HostKey)

               If TypeOf oInstance.Key Is Ed25519Key Then
                 aData = DirectCast(oInstance.Key, Ed25519Key).PublicKey
                 Exit For
               End If
             Next
           End Sub

However, the computed Base64 of aData still doesn't match the output of the Win11 SSH client. Does anyone know how those values are arrived at?

--EDIT--

OK, I'm getting closer. I now have the Windows-supplied SSH client's value for ed25519. It's a straight Base64 encoding of the server's HostKey, prior to any hashing:

Dim sBase64 = Convert.ToBase64String(e.HostKey)
' Returns AAAAC3NzaC1lZDI1NTE5AAAAICuy9wsbY7fBFFoB6K0RU/BsISB3mL4PQ3311ta0S/cW

Now to tackle getting the same for the server's rsa key.

答案1

得分: 1

以下是您要翻译的部分:

"The solution is much simpler than I had anticipated: simply Base64-encode the host's HostKey byte array without hashing it (SHA256 or MD5).

I was able to get the rsa key by requesting it at connection time:

oConnectionInfo = New PasswordConnectionInfo(Host.Name, Host.Username, Host.Password)
oConnectionInfo.HostKeyAlgorithms.Clear
oConnectionInfo.HostKeyAlgorithms.Add(sKeyType, Function(Data) New KeyHostAlgorithm(sKeyType, New RsaKey, Data))

Using oClient = New SshClient(oConnectionInfo)
  AddHandler oClient.HostKeyReceived, oHandler

  oClient.Connect
  oClient.CreateCommand("temp").Execute

  RemoveHandler oClient.HostKeyReceived, oHandler
End Using

oHandler = Sub(Sender As SshClient, e As HostKeyEventArgs)
             sBase64 = Convert.ToBase64String(e.HostKey)

             e.CanTrust = Host.Base64 = sBase64
           End Sub

This works, and I can use it to compare the host's keys with the Windows-supplied SSH client's stored keys."

英文:

The solution is much simpler than I had anticipated: simply Base64-encode the host's HostKey byte array without hashing it (SHA256 or MD5).

I was able to get the rsa key by requesting it at connection time:

sKeyType = "ssh-rsa"
oConnectionInfo = New PasswordConnectionInfo(Host.Name, Host.Username, Host.Password)
oConnectionInfo.HostKeyAlgorithms.Clear
oConnectionInfo.HostKeyAlgorithms.Add(sKeyType, Function(Data) New KeyHostAlgorithm(sKeyType, New RsaKey, Data))

Using oClient = New SshClient(oConnectionInfo)
  AddHandler oClient.HostKeyReceived, oHandler

  oClient.Connect
  oClient.CreateCommand("temp").Execute

  RemoveHandler oClient.HostKeyReceived, oHandler
End Using

oHandler = Sub(Sender As SshClient, e As HostKeyEventArgs)
             sBase64 = Convert.ToBase64String(e.HostKey)

             e.CanTrust = Host.Base64 = sBase64
           End Sub

This works, and I can use it to compare the host's keys with the Windows-supplied SSH client's stored keys.

huangapple
  • 本文由 发表于 2023年3月12日 18:23:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75712474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定