SSH with PuTTY, Pageant and PLink from the Windows Command Line

I’ve recently started using Git for my revision control needs, switching from Mercurial that I’ve previously used for a number of years.  I had mostly used Mercurial from a GUI, namely TortoiseHg, only occasionally dropping to the command line for ad-hoc Mercurial commands.

In switching to Git, I initially switched to an alternative GUI tool, namely SourceTree, however I very quickly decided that this time around, I wanted to try to use the command line as my main interface with the revision control tool.  This was a bold move as the Git syntax is something that had always put me off Git and made me heavily favour Mercurial, due to Mercurial’s somewhat nicer command line syntax and generally “playing better” with Windows.

So, I dived straight in and tried to get my GitHub account all set up on a new PC, accessing Git via the brilliant ConEmu terminal and using SSH for all authentication with GitHub itself.  As this is Windows, the SSH functionality was provided by PuTTY, and specifically by the PLink and Pageant utilities within the PuTTY solution.

imageI already had an SSH Key generated and registered with GitHub, and the private key was loaded into Pageant, which was running in the background on Windows.  The first little stumbling block was to get the command line git tool to realise it had to use the PuTTY tools in order to retrieve the SSH Key that was to be used for authentication.

image This required adding an environment variable called GIT_SSH which points to the path of the PuTTY PLINK.exe program.  Adding this tells Git that it must use PLink, which acts as a kind of “gateway” between the program that needs the SSH authentication, and the other program – in this case PuTTY’s Pageant – that is providing the SSH Key.  This is a required step, and is not the default when using Git on Windows as Git is really far more aligned to the Unix/Linux way of doing things.  For SSH on Unix, this is most frequently provided by OpenSSH.

After having set up this environment variable, I could see that Git was attempting to use the PLINK.EXE program to retrieve the SSH key loaded into Pageant in order to authenticate with GitHub, however, there was a problem.  Although I definitely had the correct SSH Key registered with GitHub, and I definitely had the correct SSH Key loaded in Pageant (and Pageant was definitely running in the background!), I was continually getting the following error:

image

The clue to what’s wrong is there in the error text – The server that we’re trying to connect to, in this case it’s github.com, does not have it’s RSA key “installed” on our local PC.  I say “installed” as the PuTTY tools will cache remote server RSA keys in the Windows registry.  If you’re using OpenSSH (either on Windows or more likely on Unix/Linux, they get cached in a completely different place). 

Although the error indicates the problem, unfortunately it gives no indication of how to correct it.

The answer lies with the PLINK.exe program.  We have to issue a special one-off PLINK command to have it connect to a remote server, retrieve that server’s RSA key, then cache (or “install”) the key in the registry to allow subsequent usage of PLINK as a “gateway” (i.e. when called from the git command line tool) to be able to authenticate the server machine first, before it even attempts to authenticate with our own SSH key.

The plink command is simply:

plink.exe -v -agent git@github.com

or

plink.exe -v -agent git@bitbucket.org

(the git@github.com or git@bitbucket.org parts of the command are the specific email addresses required when authenticating with the github or bitbucket servers, respectively).

The –v simply means verbose output and can be safely omitted.  The real magic is in the –agent command which instructs plink to use Pageant for the key:

image

Now we get the opportunity to actually “store” (i.e. cache or install) the key.  If we say yes, this adds the key to our Windows Registry:

image

Once we’ve completed this step, we can return to our command window and attempt our usage of git against our remote repository on either GitHub or BitBucket once more.  This time, we should have much more success:

image

And now everything works as it should!

SSH over SSL with BitBucket & GitHub.

I’ve recently decided to switch to using SSH (Secure Shell) access for all of my repositories on both BitBucket & GitHub.  I was previously using HTTPS access, however this frequently means that you end up with hard-coded usernames and passwords inside your Mercurial and Git configuration files.  Not the most secure approach.

I switched over to using SSH Keys for access to both BitBucket and GitHub and I immediately ran into a problem.  SSH access is, by default, done over Port 22 however this is not always available for use.  In a corporate environment, or over public Wi-Fi, this port is frequently blocked.  Fortunately, both GitHub and BitBucket both allow using SSH over the port that is used for SSL (HTTPS) traffic instead as this is almost always never blocked (Both Port 80 (HTTP) and 443 (HTTPS) are required for web browsing).

Setting this up is usually easy enough, but there can be a few slightly confusing parts to ensuring your SSH Keys are entered in the correct format and making sure you’re using the correct URI to access your repositories.  I found BitBucket that little bit easier to configure, and initially struggled with GitHub.  I believe this is primarily because GitHub is more geared towards Unix and OpenSSH users rather than Windows and PuTTY users.

Setting Up The Keys

The first step is to ensure that the SSH Key is in the correct format to be added to either your GitHub or BitBucket account.  If you’re using PuTTYGen to generate your SSH keys, the easiest way it to simply copy & paste the key from the PuTTYGen window:

puttygen

In my own experience, I’ve found that BitBucket is slightly more forgiving of the exact format of the SSH Key.  I’d previously opened my private SSH Key files (.ppk file extension) in Notepad and copied and pasted from there.  When viewed this way, the SSH Key is rendered in an entirely different format as shown below:

puttygenkeytext

It seems that BitBucket will accept copying and pasting the “public” section from this file (identified as the section between the lines “Public-Lines: 6” and “Private-Lines: 14”) however GitHub won’t.  Copying and pasting from the PuTTYGen window, though, will consistently work with both BitBucket & GitHub.

Configuring Client Access

The next step is to configure your client to correctly access your BitBucket and GitHub repositories using SSH over the HTTPS/SSL port.  Personally, I’ve been using TortoiseHG for some time now for my Mercurial repositories, but recently I’ve decided to switch to Atlassian’s Sourcetree as it allows me to work with both Mercurial & Git repositories from the same UI.  (I’m fairly comfortable with Mercurial from the command line, too, but never really got around to learning Git from the command line.  Maybe I’ll come back to it one day!)

normalsshBitBucket has a very helpful page on their documentation that details the URI that you’ll need to use in order to correctly use SSH over Port 443.  It’s a bit different from the standard SSH URI that you get from the BitBucket repositories “home page”.

normalssh2

Note the altssh.bitbucket.org domain rather than the standard bitbucket.org one!  You’ll also need to add the port to the end of the domain as shown in the image.

Configuring the client access for GitHub was a little bit trickier.  Like BitBucket, GitHub has a page in their documentation relating to using SSH over SSL, however, this assumes you’re using the ssh command line tool, something that’s there by default in Unix/Linux but not there on Windows (although a 3rd party implementation of OpenSSH does exist).  The GitHub help page suggests to change your SSH configuration to “point” your ssh.github.com host name to run over Port 443.  That’s easy if you’re using the command line OpenSSH client, but if you’re using something like Tortoise or in my case, SourceTree, that’s not so easy.

ghnormalsshThe way to achieve this is to forget about fiddling with configuration files, and just ensure that you use the correct URI, correctly formed in order to establish a connection to GitHub with SSH over SSL.  The standard SSH URL provided by GitHub on any of your GitHub repository homepages (as shown in the image) suggests that the URL should follow this kind of format:

git@github.com:craigtp/craigtp.github.io.git

That’s fine for “normal” SSH access where SSH connects over the standard, default port of 22.  You’ll need to change that URL if you want to use SSH over the SSL port (Port 443).  The first thing to notice is that the colon within the URL above separates the domain from the username.  Ordinarily, colons in URLs separate the domain from the port number to be used, however here we’re going to add the port number separated by a colon from the domain and move the username part to be separated after the port number by a slash.  We also need to change the actual domain from git@github.com to git@ssh.github.com.

ghsshssl

Therefore our SSH over SSL URL becomes:

git@ssh.github.com:443/craigtp/craigtp.github.io.git

instead of:

git@github.com:craigtp/craigtp.github.io.git

(Obviously, replace the craigtp.github.io.git part of the URL with the relevant repository name!)

It’s a simple enough change, but one that’s not entirely obvious at first.

Mercurial Pushes and the authorization failure of doom!

 

imageEver get the notorious “abort: authorization failed” message from a Mercurial “push” command??

 

You are not alone!

 

It seems the way to fix this is to always ensure that the Bitbucket username is specified within the “remote repository” URL!

 

imagei.e. the remote repository URL should be something like “https://craigtp@bitbucket.org/craigtp/fizzbuzz” and NOT “https://bitbucket.org/craigtp/fizzbuzz” – See the screenshot to the right.  In this case, my username is “craigtp”, obviously, replace that with your own username for your own repository/Bitbucket account.

 

Bizarrely, this is still required to get around the “authorization failed” issue even though TortoiseHg will prompt you at runtime for both your Bitbucket username and password (if the username is not specified in the URL).  Once you’ve specified your username in the URL, you’re no longer prompted for it, only the password, however the “abort: authorization failed” issue will go away!

 

UPDATE:

I’ve done further digging since posting this article, and unfortunately, I’m not convinced that this is the exact answer to the authorization problem.  Doing the above certainly fixed my specific problem at the time I had it, in the very specific circumstances of my environment (which including accessing BitBucket via a rather fussy proxy server) however I’ve since been able to happily make Mercurial pushes to BitBucket without having to specify the username in the remote repo URL in different environments.  My research on this matter continues!