在SSH.Net中检查sftp指纹

rom*_*zor 4 security

我正在创建一个SSIS包,我需要连接到安全服务器来复制一些文件,我想通过服务器发送的公钥指纹来验证连接.

我对这个领域不是很熟悉,我能不能期望在连接时发送指纹?

该软件包以前使用过WinScp,指纹以"ssh-dss 1024 [hex representation]"格式烘焙到代码中.我假设这种格式取自PuTTY,因为这是我在连接到新服务器时看到的,它要求我验证.WinScp按原样使用并处理验证.

我打算切换到SSH.Net,它的机制要求我手动检查指纹.我可以仅根据十六进制验证连接,还是需要检查密钥长度和使用的算法?

Vin*_*niH 10

您可以仅基于十六进制来执行此操作 - 首先您要编写(或复制/使用)实用程序方法将十六进制字符串转换为字节数组(这取决于十六进制字符串的格式) - 示例下面是用于转换由冒号分隔的字符串(例如"1d:c1:5a:71:c4:8e:a3:ff:01:0a:3b:46:17:6f:e1:52")

    public static byte[] ConvertFingerprintToByteArray( String fingerprint )
    {
        return fingerprint.Split( ':' ).Select( s => Convert.ToByte( s, 16 ) ).ToArray();
    }
Run Code Online (Sandbox Code Playgroud)

然后,您只需附加到sftpClient对象的HostKeyReceived事件.

SftpClient sftpClient = new SftpClient( Hostname, Username, Password );
sftpClient.HostKeyReceived += delegate ( object sender, HostKeyEventArgs e )
{
    if( e.FingerPrint.SequenceEqual( ConvertFingerprintToByteArray( "1d:c1:5a:71:c4:8e:a3:ff:01:0a:3b:46:17:6f:e1:52" ) ) )
        e.CanTrust = true;
    else
        e.CanTrust = false;
};
Run Code Online (Sandbox Code Playgroud)

如果此检查失败,则SSH.net将抛出SshConnectionException - 并显示"密钥交换协商失败"消息.

希望这可以帮助.


Mar*_*ryl 6

@ViniH 的答案曾经是正确的,但现在已经过时了。如今,您需要使用 SHA-256 哈希值,而不是 MD5。要计算 SHA-256,您可以将System.Security.Cryptography.SHA256class与 一起使用HostKeyEventArgs.HostKey

此外,您可能想使用Convert.ToBase64StringSHA-256 指纹的通用 Base64 表示形式

sftpClient.HostKeyReceived += (object sender, HostKeyEventArgs e) =>
{
    string sha256Fingerprint =
        Convert.ToBase64String(SHA256.Create().ComputeHash(e.HostKey));

    e.CanTrust =
        (sha256Fingerprint == "1hI1HqP3IzoOWCABHGS7+GsrP2JUVsSs7oskK7HGP1E=");
};
Run Code Online (Sandbox Code Playgroud)

在旧版本的 .NET 中使用new SHA256Managed().ComputeHash代替。SHA256.HashData


如果您想比较完整的主机密钥(采用 OpenSSHknown_hosts文件中看到的格式),只需对以下内容进行 Base64 编码e.HostKey

Convert.ToBase64String(e.HostKey)
Run Code Online (Sandbox Code Playgroud)