1. Introduction

The Secure Shell (SSH) protocol has spread out from the UNIX world as the open-source alternative to proprietary options. Being integrated into Microsoft Windows, Apple macOS, and most Linux distributions, it’s available in more systems than most can enumerate. However, this doesn’t imply that there aren’t drawbacks to this cross-platform operation.

In this tutorial, we look at ways to convert the native key format of one SSH client-server combination to another. First, we discuss two SSH tool suites. After that, we delve into the key types and formats supported by each implementation. Finally, we talk about key conversions between the different formats.

For brevity and security reasons, we only consider the newest iteration of SSH version 2 (SSHv2) as implemented by OpenSSH and PuTTY.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4, OpenSSH 8.4p1, and PuTTY 0.77. It should work in most POSIX-compliant environments.

2. OpenSSH and PuTTY

Despite being the industry-standard implementation of SSH, OpenSSH is by far not the only way to use the protocol. In fact, until recently, PuTTY was the predominant SSH client on Windows platforms.

2.1. OpenSSH

As already outlined, OpenSSH is the de facto method for remote access to Linux systems. The package names on most platforms are openssh, openssh-server, and openssh-clients. Still, we can install the OpenSSH server on Windows as well.

In addition, the openssh* packages include a suite of tools:

In summary, there are three services (sshd, sftp-server, and ssh-agent), four key management tools (ssh-add, ssh-keysign, ssh-keyscan, and ssh-keygen), and three client utilities (ssh, scp, and sftp).

2.2. PuTTY

As the most popular SSH client, PuTTY has been a staple in Windows for remote SSH access. Of course, there is a version available for Linux via the putty or putty-tools packages. It’s even possible to install it as putty on macOS via homebrew.

Moreover, PuTTY has a graphical user interface (GUI) exposing most of its functions. Indeed, this is perhaps one of the main reasons for its popularity among Windows users. Along with the main putty client, the package also contains other tools:

  • pageant, the authentication agent equivalent to ssh-agent, which also stores decoded private keys for easy access
  • psftp, similar to sftp, allows the transfer of files via the SSH File Transfer Protocol (SFTP)
  • plink, the automation-friendly version of putty, which more closely mimics the ssh client
  • pscp, a secure copy client similar to scp
  • puttygen, the key management tool similar to ssh-keygen

One thing PuTTY lacks is a server component. That means it still relies on implementations like OpenSSH to use its client utilities.

However, the putty and plink tools support even more ways to connect:

Now, let’s turn to one of the standard and most secure authentication methods – keys. Indeed, SSH connections require a public and private key. Despite being based on the same protocol, SSH clients may use different key formats and default types. Actually, not all SSH servers accept every type of key.

3. SSH Key Types

In general, there are four widespread key types by algorithm:

However, OpenSSH deprecated DSA entirely, along with RSA’s combination with SHA1 (SSHv1 RSA) on the signature side. Yet, both ssh-keygen and puttygen can generate them along with other types.

Even when DSA was available, puttygen could still generate DSA keys that don’t conform to the 1024-bit requirement of OpenSSH, making them unusable on that front.

Furthermore, Elliptic Curve Cryptography (ECC) keys make session setup relatively quicker, but only recent OpenSSH versions support them.

With all this in mind, even if a key is of the proper type, it can be in an unsupported format.

4. SSH Key Formats

While keys are only big numbers, clients usually generate them in formats that make them more recognizable.

4.1. OpenSSH Key Format

For example, let’s explore the default OpenSSH public and private key formats:

$ ssh-keygen -f id_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa
Your public key has been saved in id_rsa.pub
$ cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABg[...]bEfYB+Acc3raPf8= baeldung@web
$ cat id_rsa

As we can see above, both of these formats have several human-friendly characteristics:

  • key type (first column, ssh-rsa) for the public key
  • free-text comment field (last column, baeldung@web) for the public key
  • header and footer for the private key
  • keys encoded in base64

Of course, all of these aren’t strictly necessary, but they make it more convenient for an administrator or user to handle them. Also, PuTTY can use the default OpenSSH keys directly.

4.2. PuTTY Key Format

In fact, PuTTY takes convenience a step further with its default .ppk format:

$ puttygen -t rsa -o pp_id_rsa.ppk
$ cat pp_id_rsa.ppk
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: rsa-key-20221010
Public-Lines: 6
Private-Lines: 14
Private-MAC: d982e785ce2981423ad0af42d34657aece9c9c7d

In this case, we have fields for each category of data and metadata:

  • PuTTY key format (PuTTY-User-Key-File-2) specified at the top
  • key type (ssh-rsa) field
  • Encryption field, specifying whether the key is protected
  • free-text comment field
  • the public and private keys are in the same file
  • the public key is in plaintext even if the private key is password-protected
  • keys encoded in base64
  • error checking and formatting via key line counts
  • tamper proofing with a Message Authentication Code (MAC)

Naturally, the improved .ppk format isn’t directly compatible with OpenSSH clients.

After discussing the types and some formats for SSH keys, let’s see how we can convert between them. Of course, all steps with puttygen also work in the GUI version of the tool.

5. Split .ppk Into Separate Keys via puttygen

To begin with, we can get the public and private keys from our combined pp_id_rsa.ppk file.

First, let’s get the public key in two formats:

$ puttygen pp_id_rsa.ppk -O public-openssh -o id_rsa.pub
$ cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAnM+ageku7aa36w6bQ4oaU0qROzLRCfC6l/0j[...]lQa/HnPmKpMlwBP6qxMdfaDVLx5Q== rsa-key-20221010
$ puttygen pp_id_rsa.ppk -O public -o pp_id_rsa.pub
$ cat pp_id_rsa.pub
Comment: "rsa-key-20221010"

In the initial command, the -O flag to puttygen specifies the public-openssh (OpenSSH) format for the id_rsa.pub output (-o) file generated from pp_id_rsa.ppk. After checking the result, we again use puttygen for exporting to pp_id_rsa.pub in the public (PuTTY) format. Note the differences between these two files, despite their same key content. One is compatible with OpenSSH, while the other isn’t.

Next, we can extract the private key:

$ puttygen pp_id_rsa.ppk -O private-openssh -o id_rsa

Importantly, the private key for PuTTY is only available in the merged .ppk format. In the case of a passphrase-protected .ppk, we’d get a Enter passphrase to load key prompt. Now, we have a so-called .pem file with the private key, which is also compatible with OpenSSH.

6. Convert a PuTTY Public Key to the OpenSSH Format via ssh-keygen

At this point, having the pp_id_rsa.pub public key from puttygen, we can use ssh-keygen to convert it to OpenSSH:

$ cat pp_id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAnM+ageku7aa36w6bQ4oaU0qROzLRCfC6l/0j[...]nXEnQ3mVZMqz+tUp0hFqlFlQa/HnPmKpMlwBP6qxMdfaDVLx5Q== rsa-key-20221010
$ ssh-keygen -i -f pp_id_rsa.pub > id_rsa.pub
$ cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAnM+ageku7aa36w6bQ4oaU0qROzLRCfC6l/0j[...]nXEnQ3mVZMqz+tUp0hFqlFlQa/HnPmKpMlwBP6qxMdfaDVLx5Q==

First, we output the original PuTTY public key pp_id_rsa.pub. After that, we convert the PuTTY file specified after -f with the -i import flag to ssh-keygen. Finally, we output the result to id_rsa.pub and display its contents.

7. Summary

In this article, we discussed PuTTY and OpenSSH, their key types and formats, as well as how to convert between them.

In conclusion, SSH is a standard protocol with different implementations, but there are ways to achieve inter-compatibility via integrated tooling.

Comments are closed on this article!