英文:
How to convert SSH host keys for validation?
问题
使用 SSH.NET
,我正在尝试从我的 SSH 主机(在这种情况下是树莓派)中获取与 Windows SSH 客户端获取的相同的 ed25519
和 rsa
主机密钥,以便我可以将它们与 %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
(特别是 ed25519
和 rsa
)中的内容匹配的方式从 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论