I am using ssh.net to transfer files through SFTP protocol. I need to validate host key fingerprint as an extra layer of security. For that, I wrote a method to convert the string to byte array to compare as I saved the host key as string in my xml configuration and the SFTP client brings the host key as byte array.
using System;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Channels;
using FsLogger;
using Renci.SshNet;
namespace FsUtils.FileOperations
{
public class FtpHandler
{
public string User { get; set; }
public string Password { get; set; }
public string Server { get; set; }
public void UploadFileSftp(string sourceFile, string targetDir, string sshHostKeyFingerprint)
{
using (var client = new SftpClient(Server, User, Password))
{
client.HostKeyReceived += (sender, e) =>
{
byte[] receivedFingerprint = e.FingerPrint;
byte[] providedFingerprint = StringToByteArray(sshHostKeyFingerprint);
e.CanTrust = receivedFingerprint.SequenceEqual(providedFingerprint);
};
try
{
client.Connect();
if (client.IsConnected)
{
using (var fileStream = File.OpenRead(sourceFile))
{
client.UploadFile(fileStream, targetDir);
}
}
Logging.Info("File uploaded successfully");
}
catch (Exception ex)
{
Logging.Error($"Exception occurred - {ex.Message}");
}
finally
{
if (client.IsConnected)
client.Disconnect();
}
}
}
private byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
}
}
And this is where Sftp uploader method gets called-
using FsLogger;
using FsUtils.FileOperations;
using System;
using System.IO;
using System.Reflection;
namespace FsFtpImport
{
public class FtpImporter
{
public FtpImportConfig Config { get; set; }
private FtpHandler ftpHandler;
public void Start()
{
if (Config == null)
{
Logging.Info("Config not found (NULL)");
return;
}
try
{
ftpHandler = new FtpHandler
{
User = Config.FtpUser,
Password = Config.FtpPassword,
Server = Config.FtpServer,
};
foreach (FolderMapping folderMap in Config.FolderMappings)
{
string[] files = Directory.GetFiles(folderMap.ClientDirectory);
foreach (string file in files)
{
Uploadfile(file, folderMap.FtpDirectory,Config.SshHostKeyFingerprint);
}
}
}
catch (Exception ex)
{
Logging.Exception(ex, MethodBase.GetCurrentMethod().Name);
}
}
private void Uploadfile(string file, string targetdir,string fingerprint)
{
try
{
switch (Config.Protocol)
{
case FtpProtocol.Sftp:
{
this.ftpHandler.UploadFileSftp(file, targetdir,fingerprint);
break;
}
default:
{
Logging.Error("unknown protocol");
break;
}
}
if (Config.DeleteSourceFiles)
File.Delete(file);
}
catch (Exception ex)
{
Logging.Error($"Error uploading file {file}");
Logging.Exception(ex, MethodBase.GetCurrentMethod().Name);
Logging.Info("File skipped");
}
}
}
}
Now the problem is while converting my string host key to byte array, it throws exception.
<![LOG[Failed: Exception occurred - Additional non-parsable characters are at the end of the string.]LOG]!>
I collected the host key from the knwon-hosts file and copied the key along with its encryption algorithm. It looks like this-
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBP4cDyvxP/kbZ1XrPxxyMshbTtrY605xu5VL37uZt9mv7d2ZqD3TSWoEcUgHgtzGuRzkGTfDXdT9J=
How to validate the host key fingerprint without any issues? I greatly appreciate your kind help.