Multi-Factor Authentication with Password and Private Key File in SSH.NET

If you want to use SSH.NET to connect to an SFTP server that requires both a password and a private key file, you’ll be happy to know that it is well supported! Unfortunately (and similar to my previous SSH.NET post about modifying the Host Key Algorithm) the documentation doesn’t really make it clear how to do this.

As an example, let’s grab the code sample from the SSH.NET documentation on multi-factor authentication. At time of writing it looks as follows:

var connectionInfo = new ConnectionInfo("sftp.foo.com",
    "guest",
    new PasswordAuthenticationMethod("guest", "pwd"),
    new PrivateKeyAuthenticationMethod("rsa.key"));

using (var client = new SftpClient(connectionInfo))
{
    client.Connect();
}

If you modify the server address, username and password and then run it you’ll quickly hit a brick wall in the shape of this error message:

Renci.SshNet.Common.SshAuthenticationException: Permission denied (publickey).

The first issue that we’re running into is that we’re not actually specifying the private key details anywhere! Let’s change that (I’ve also swapped the literal strings out for some variables):

string _privateKeyPath = "";
string _privateKeyPassPhrase = "";
string _host = "";
string _username = "";
string _password = "";

var keyFile = new PrivateKeyFile(_privateKeyPath, _privateKeyPassPhrase);
var keyFiles = new[] { keyFile };

var connectionInfo = new ConnectionInfo(_host, _username,
    new PasswordAuthenticationMethod(_username, _password),
    new PrivateKeyAuthenticationMethod("rsa.key", keyFiles));

using (var client = new SftpClient(connectionInfo))
{
	client.Connect();
}

Now if you run this you’ll get a new error (#ProgressIsProgress), this time telling you that you’re not allowed to change username:

Renci.SshNet.Common.SshConnectionException: The connection was closed by the server: Change of username or service not allowed: (<USERNAME>,ssh-connection) -> (rsa.key,ssh-connection) (ProtocolError).

Now when I first ran into this error and threw it into Google I got very few results; looks like we’re treading new ground!

The fix for this is actually really simple; the constructor for PrivateKeyAuthenticationMethod takes a username as the first parameter! For some reason this is set to “rsa.key” in the official documentation rather than “guest” which they use as the username placeholder on the two lines above, so when I first looked into this issue I wrongfully assumed that it was a string specifying what type of private key was being consumed!

The only change we need to make to the previous example is to swap in the _username variable (or a literal string of the username if you prefer) for the first parameter of the PrivateKeyAuthenticationMethod constructor.

string _privateKeyPath = "";
string _privateKeyPassPhrase = "";
string _host = "";
string _username = "";
string _password = "";

var keyFile = new PrivateKeyFile(_privateKeyPath, _privateKeyPassPhrase);
var keyFiles = new[] { keyFile };

var connectionInfo = new ConnectionInfo(_host,
    _username,
    new PasswordAuthenticationMethod(_username, _password),
    new PrivateKeyAuthenticationMethod(_username, keyFiles));

using (var client = new SftpClient(connectionInfo))
{
	client.Connect();
}

Run it now, and you should connect successfully!

Regular Expression Tips for People That Hate Regular Expressions

A screenshot of a code editor. There are three lines, setting the variables "isCustomerNumber", "isProductNumber" and "isTransactionNumber" based on whether a series of regular expression (regex) matches succeed

I’ve been writing regular expressions (regex) for years and would consider myself pretty good at them by now (I decline to provide references). The problem is that although it’s common to see regex as cryptic and painfully terse (which are not invalid points), they remain one of the best ways to handle complex pattern matching and as such you’ll probably run into them at least a few times in your career.

Even if you really despise writing regular expressions, here are some tips that will help to make that process as painless as possible!

Continue reading “Regular Expression Tips for People That Hate Regular Expressions”

Epson ET-2711/ET-2710 Series Printer Wireless Setup Made Easy

A photo of an Epson ET-2711 printer

If you want to just get to the good stuff, scroll down to the “Setup” section.

My wife and I finally got a new printer to replace the old one that has pretty much given up the ghost and refuses to print anymore (often considered an important feature for devices like this).

We settled on an Epson ET-2711 in large part because of the ink tank that should (hopefully) do away with the constant stream of expensive cartridges in favour of some cheaper-per-page ink bottles. I was excited to get it out and start setting it up (in part because we’re in another lockdown and what else is there to do right now)!

Imagine my frustration, dear reader, when I found out that the whole wireless setup process for this printer is terrible if you follow the official instructions. I genuinely spent a couple of hours bouncing between the Android app (which gave me a very helpful message telling me “Communication error”, to check the printer is on and not much else), the included software for Windows (which was just as helpful), the printed documentation in the box and the website, all to no avail.

You cannot convince me that this is a helpful error message

The good news is that I finally figured out how to get it working. The even better news for you at home is that I’ve gone through the process three times so that I could document all of the steps to get this working properly!

Continue reading “Epson ET-2711/ET-2710 Series Printer Wireless Setup Made Easy”

Migrating from KeePass to 1Password

An image of the KeePass and 1Password logos, with an arrow pointing from KeePass to the stylised "o" in 1Password

I’ve been using KeePass for my password management needs since early 2014, but I recently decided that I wanted to move to something a bit more substantial. KeePass is an excellent (open source!) piece of software, but since it stores passwords in a single database file the only way that I could really sync it between multiple computers and my phone was to store that file… in Dropbox.

Yeah, as you can imagine that’s not a great solution.

Anyway, I wanted to move over to 1Password but when I tried searching for “Migrate KeePass to 1Password” I kept seeing references to 3rd party scripts I’d need to use to convert my exported data (no thanks) or that it would require a bunch of manual data entry. After giving it a go though, I can tell you it was actually ridiculously easy and straightforward and didn’t require any external tools or scripts! As such, I decided to put together this step-by-step tutorial for migrating your data from KeePass to 1Password!

Continue reading “Migrating from KeePass to 1Password”

So You Want to Run Azure Functions Using .NET 5

I’ve spent the last couple of evenings trying to get a set of Azure Functions migrated from .NET Core 3.1 to .NET 5 so that I can play around with some of the nice new syntax options, nullable contexts and the like. Since .NET 5 has officially been released, it would be justifiable to believe that it would be well supported across the core Microsoft product catalogue, such as in… say… Azure Functions?

Ha! You’re a funny one.

Continue reading “So You Want to Run Azure Functions Using .NET 5”

Changing Host Key Algorithm in SSH.NET

I’ve used SSH.NET a lot over the years to send and receive files using SFTP and it’s a very flexible and practical library, but the documentation can be a bit thin on the ground when you’re looking to use some of the more esoteric features it has.

As an example, I recently ran into an issue where I was connecting to a remote server and the host fingerprint I was receiving through SSH.NET didn’t match the one that I expected to see (and could see in WinSCP). After verifying that I was using the same connection settings on both and more than a little spelunking through the SSH.NET source code I found that by default the host key algorithms used by the stable release of SSH.NET that I was on (2016.1.0) are RSA and DSA, while WinSCP uses Ed25519. For my purposes I needed to use Ed25519 in SSH.NET as well even though the SFTP host also supported these other algorithms.

Continue reading “Changing Host Key Algorithm in SSH.NET”