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.
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.
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:
- scp, a tool and protocol for copying files between machines securely
- sftp, another tool and protocol for secure copying of files over a secure version of the File Transfer Protocol (FTP)
- ssh, remote SSH client, configurable via /etc/ssh/ssh_config
- ssh-add, utility for adding keys to the authentication agent
- ssh-agent, authentication agent that stores decoded private keys for easy access
- ssh-keysign, for setting up hostbased authentication
- ssh-keyscan, to get public keys from a number of SSH servers
- ssh-keygen, for secure SSH key generation
- sshd, the main SSH server daemon, configurable via /etc/ssh/sshd_config
- sftp-server, an SFTP server component
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).
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 Secure 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:
- Digital Signature Algorithm (DSA)
- Rivest-Shamir-Adleman (RSA)
- Elliptic Curve DSA (ECDSA)
- EdDSA and Ed25519
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= [email protected] $ cat id_rsa -----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBYhnRMTA W+Pp1cNt8EK0oPAAAAEAAAAAEAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQDPpRMaDM0c 8uP1nm5FGrYHMJaM8W+T8IctzQRKkDM8BVt4QvcJq014eg+JYEgh34ZzMYNqw0EDfq0zbs [...] 7IJPJBfNlut/6tznN+OE0tHRBDLfgSLI4C3WN58iXQTlAxcpMUMcGSsoQPVSML3pTex1+u RqaqsyYqvQRhtSYh3b2ODsuO+4j6hy/zLJvXk0Wlhqy/g2USGfIIMF2vKcIX5vk/xPjDpQ SMXWTQ== -----END OPENSSH PRIVATE KEY-----
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, [email protected]) 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 AAAAB3NzaC1yc2EAAAABJQAAAQEAsWfZeLNCKr9OiYmzb4dJAlnno+DyHPHTvEHY [...] 7I/KC/MlE4WMn7VVeLZK4TPWMAv2r+gxKelJYQZzafgdXUIPaQ== Private-Lines: 14 AAABAQCBdUurGwbFP36AConbw5YkT3Gu8EH5cjK5zy9cvuNrrFuZa2X2mtH6VqFq YfDNWx+Fd/34s5+g3cjvuUyoEEngGnp4Ncqy3+LdzcsyFAWHofQd6NfwMZ2Hu+L+ [...] 4unNqF+o/gF0eZOBFy9ePzyIYPwhgvcWUaR5hh+rKCf9GSkH2cIUrfSO3NIlzw59 I7EN8BPjNKe+XilJJTBL4ia9jKdUzW6DghAENDJ7QaXC8JR3 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 ---- BEGIN SSH2 PUBLIC KEY ---- Comment: "rsa-key-20221010" AAAAB3NzaC1yc2EAAAABJQAAAQEAnM+ageku7aa36w6bQ4oaU0qROzLRCfC6l/0j [...] nXEnQ3mVZMqz+tUp0hFqlFlQa/HnPmKpMlwBP6qxMdfaDVLx5Q== ---- END SSH2 PUBLIC KEY ----
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.
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.