- Public Ssh Key
- Ssh Public Key Authentication Failed Unable To Extract Public Key From Private Key File
If you just want to share the private key, the OpenSSL key generated by your example command is stored in private.pem, and it should already be in PEM format compatible with (recent) OpenSSH. To extract an OpenSSH compatible public key from it, you can just run: ssh-keygen -f private.pem -y private.pub. Public Key authentication for SSH - improve security, enable automatic log in without passwords.
I want to extract the public and private key from my PKCS#12 file for later use in SSH-Public-Key-Authentication. Right now, I'm generating keys via ssh-keygen which I put into.ssh/authorizedkey. SSH public key file format as specified in RFC4716. SSH private key file format must be PEM. Create an RSA key. Amazon EC2 does not accept DSA keys. The supported lengths are 1024, 2048, and 4096.
2019-01-12Or the result of several hours of fumbling around trying to use my new Feitian ePass Smart Card to login on my ssh server with asymmetric cryptography...
Table of Content
- Surely, it can't be too hard, right?
- Using the key pair with SSH
- It was too good to last, or 'why does connecting from a Windows host have to be so hard?'
- Satisfying Putty-CAC by creating a certificate from our key pair
- Succeeding on Ubuntu
- Finally getting it to work on Windows
- Satisfying Putty-CAC by creating a certificate from our key pair
- Conclusion
Surely, it can't be too hard, right?
The idea is simple: Public Key Authentication for SSH is well documented, I just want my private key to live on my hardware token instead of being a file on my hard drive.
Thanks to my job, I already had (some) experience with OpenSSL, OpenSC, PKCS#11 and PKCS#15, and it's not like these technology are new, so I was expecting it would be simply a matter of finding the right commands.
After I managed to enable the Smart Card capability of the token, I continued with the Feitian guide on how to use their product with SSH authentication...
Accessing the token on Windows
Since OpenSC and OpenSSL are Unix tools, my first instinct was to use WSL (Windows Subsystem for Linux) to access the token. Unfortunately, WSL does not support libusb (yet?), meaning it's not possible.
So I installed the latest release of OpenSC for Windows and verified it worked:
Creating a new key pair
I then created a new RSA key pair:
Note: Not all key sizes are supported by all tokens. Some tokens also support some Elliptic Curves, but OpenSC's PKCS#15 tools could only create RSA keys up until recently, though I believe it's also possible to use OpenSC's PKCS#11 tools to create keys on the token...
To use this key pair with SSH, we need to export the Public part in the right format. Fortunately, there is a command to do just that:
Using the key pair with SSH
Server side
The output of the previous command can directly be added into the authorized_keys
file of an OpenSSH server (located in the .ssh
directory).
Note: OpenSSH requires restrictive permissions on the authorized_keys
file, so in case it doesn't work, run chmod 600 authorized_keys
.
Client side
On Unix systems, it should work using OpenSSH's PKCS#11 builtin support (with OpenSC installed):
Tadaaa! Done!
Note: I did not actually test this scenario without first getting it to work on Windows by adding a certificate to the token, so in case nothing happens, read on.
It was too good to last, or 'why does connecting from a Windows host have to be so hard?'
I don't typically use OpenSSH from Windows. I use PuTTY. Unfortunately, even though it seems this is a common feature request, PuTTY does not support Smart Cards 🙁
Some forks adding support of Smart Cards exist. Some are free, some require the user to pay for a license, but none seem very trustful or up to date.
Because of that, I tried to use OpenSSH anyway.
Unfortunately, the version currently shipped with Windows does not support PKCS#11:
I tried to install a more recent binary release, but it only failed in a different way...
As I said previously, WSL is out of the question (libusb not supported), so as a last resort, I created an Ubuntu HyperV virtual machine, hoping I would be able to share an USB device with it...
Except it's apparently only supported through remote desktop on Windows VMs. 😑
Putty-CAC
After going back to testing a few PuTTY forks, I saw the OpenSC page on SSH recommends Windows users to use Putty-CAC, so that's what I ended up doing.
Again, the documentation is sparse, so I spent a good while not understanding why it didn't work.
It turns out Putty-CAC (and all the other forks I tried) does not support authenticating with a simple Private key.
Public Ssh Key
It requires a certificate with the key...
Satisfying Putty-CAC by creating a certificate from our key pair
Failing on Windows
The PKCS#15 tools we used to generate a key pair are able to store a certificate, but cannot create one.
This is a job more suited for OpenSSL.
OpenSSL commands to do that are not very user-friendly, but are relatively well documented. Unfortunately, in this case the Private key we want to use cannot leave the token, so we must tell OpenSSL how to access with it via PKCS#11.
This is normally just some arguments to add, with the path of the PKCS#11 library to use, but OpenSSL and OpenSC are Unix-first tools, and I didn't manage to get this to work on Windows...
After trying other releases of OpenSSL without getting it to output something more useful than a stack trace, I gave up and decided to use my Ubuntu dual boot...
Succeeding on Ubuntu
Required packages
Starting from the Ubuntu 18.10 Desktop Live USB.
Note: I'm not entirely sure libengine-pkcs11-openssl
is required.
Some packages are in the universe
repository so I first had to add it:
Once this is done, we can continue to the interesting part...
Give me the command line already!
The documentation on how to use PKCS#11 with OpenSSL sucks, and a lot of old pages show dreadful commands such as the following, supposed to be required to initialize the engine:
After failing to make the above command work for a while, and after some more googling, I found out that, at least on a modern Ubuntu system, it is actually a lot easier (for once).
So without more delay, here is the actual command I used to generate my certificate:
Things of note:
RSA2k48
is the name of my key pair on the token- don't forget to set the expiration date explicitly. It's only a few months by default
- don't forget to add
-utf8
if you want to be able to set non-ascii characters in a way that works on different OSes (Windows in particular does not decode properly the default encoding)
Storing the certificate on the token
With the value of --id
being the id of my existing key on the device:
We can verify it worked:
In case of mistake: replacing the certificate
On my first try, I forgot to add the -utf8
argument.This resulted in a messed-up encoding on Windows, so I had to re-generate a certificate and replace the existing one on my token.
It's supposed to be easy, but sometimes it's not:
I'm not sure why it didn't work. The --update-certificate
is apparently not supported on all devices or in all cases, so I tried to simply delete the certificate before re-adding it manually:
It's not really better...
Because I was getting desperate, I tried the same command on Windows...
And it worked!!
I'm still not sure why it worked on Windows but not on Ubuntu. It's possible a bug has been fixed between OpenSC 0.18 (on Ubuntu, from the package manager) and 0.19 (on Windows, from github), but I have no certainty...
Anyway, I managed to delete the certificate on Windows, regenerated it properly on Ubuntu, and I was able to try again with Putty-CAC.
Finally getting it to work on Windows
Putty-CAC supports two different ways to get the certificate from the token: via a PKCS#11 provider (an OpenSC dll), or via Microsoft's CryptoAPI.
PKCS#11 provider
The PKCS#11 way obviously requires a PKCS#11 library, and in our case, it's the one from OpenSC.
Using this provider requires us to select the C:Program FilesOpenSC ProjectOpenSCpkcs11opensc-pkcs11.dll
file. After that, if the token is plugged-in, it should be possible to select our certificate from the selection popup.
Microsoft CryptoAPI (CAPI) provider
I only realized after I got it to work with the PKCS#11 provider that using the Microsoft CAPI is possible, and there is a nice bonus: it doesn't require anything else to be installed (beside Putty-CAC)!
Conclusion
I easily spent 5+ hours on this!
It's incredible technology that has been around from at least the 90's is still so hard to use.
Maybe hardware security token still being kind of niche can explain the lack of polish on the whole UX?
I'm not sure. But it surely won't get mainstream if it stays like that...
Anyway, in the end I didn't waste my time (too much): I can now do something actually useful with my security token. 🙂
What's next?
I will have to find a practical way to keep my token around... Why is it so hard to find necklaces or similar for this purpose?
I still haven't managed to use it with KeePass (There are plugins, but I didn't find one that work with Android yet), by maybe that's for another time...
I can't backup my private key (by design).
Maybe giving up a little security by generating the key on my PC (so I can backup it) instead of directly on the device would be more sensible? For now, I don't use the token as the sole authentication method, so I would't be locked out of my systems if I lost the key, but still...
The comment is shown highlighted below in context.
JavaScript is required to see the comments. Sorry...
This page attempts to explain public keys, as used in SSH, to readers unfamiliar with the concept.
The following concepts need to be understood by everyone, including beginner users:
A private key is a very large, pseudo-randomly generated number, that contains your secret information in any operation involving public keys. You generate the private key on your computer, using one of a variety of programs, and store it securely. You need to keep your private key secure; you never send it to anyone.
A public key is a very large number, mathematically derived from your private key. It is derived in such a way that the two numbers are linked, but so that the private key cannot be discovered by anyone who only knows the public key. The public key is what you send to other parties, to whom you want to authenticate yourself, or to whom you want to send encrypted messages. The public key is not sensitive, and does not need to be protected. It is public.
A signature is a result of a cryptographic calculation that can be performed only by a person who holds a private key, and can be verified by anyone who knows the corresponding public key. If a person is able to produce a valid signature of random data on demand, this proves that they have access to the private key associated with a particular public key.
A keypair is the combination of the private key and the public key. A keypair by necessity includes the private key, so a full keypair ought to be protected just like a private key.
A fingerprint is a cryptographic digest that can be used to uniquely identify a public key. Fingerprints are used for practical purposes, to compare keys which would otherwise be too large and unwieldy to compare manually. The most common fingerprint formats used in SSH are the SHA-256 format (example - 'C+VpXsf...'), the MD5 format (example - '43:71:be:ab:d3:...'), and the Bubble-Babble format (example - 'xubem-kiloc-getad-ponyh-...'). Like a public key, the fingerprint is not sensitive information, and can be disclosed indiscriminately.
A certificate is a public key, cryptographically signed by a certification authority (CA) in a public key infrastructure (PKI). The most widely used certificate standard is X.509. In the way SSH is most commonly used, it does not support certificates. Certificates are used primarily in TLS (SSL), which is a different protocol from SSH that serves a similar purpose. Most common SSH implementations only use raw public keys and private keys.
SSH sessions use public keys for two main purposes: server authentication, and client authentication. Both processes work very similarly, but they involve separate sets of keys. When discussing a specific public key in the context of SSH, it is important to be aware whether the key is intended to authenticate the server, or a client.
In Bitvise SSH Server:
Keys that are used for server authentication in SSH are displayed in the Host keys section of the Bitvise SSH Server Control Panel, and can be configured through the link Manage host keys. This section manages private keys, which are stored by the SSH server so it can authenticate itself to clients that connect to it.
In Keypair management, you can use the Export feature to export the public key associated with each host authentication keypair. You can send such a public key to an SSH client, so it will be able to authenticate the SSH server when it connects to it. If you do not send the client the whole public key, you should at least provide the user with your server's host key fingerprint, so that the user can confirm the server's public key is correct when they see it. The server's host key fingerprints can be viewed and copied from the main screen of the Bitvise SSH Server Control Panel.
Keys that are used for client authentication are managed through individual account settings entries. To view or configure these keys, open Easy or Advanced SSH server settings, and open a specific Windows or virtual account entry. Within this entry, find the link named 'Public keys'. This link opens a dialog which can be used to import, export, or remove public keys that the client can use to log into the server.
The SSH server will allow a client to add or remove keys themselves if 'Allow public key management' is enabled in the user's account or group settings entry in Advanced SSH server settings, or if 'Synchronize with authorized_keys' is enabled in Advanced settings > Access control.
If you are trying to configure public key authentication for a client connecting to Bitvise SSH Server, check also the Public Key Authentication section of our Bitvise SSH Server Usage FAQ.
Since versions 8.xx, the SSH Server also supports FTPS. FTPS is a file transfer protocol which uses TLS, not SSH; and TLS does use X.509 certificates. The SSH Server Control Panel includes a Manage certificates interface which allows you to generate a self-signed certificate or a certificate signing request (CSR) to obtain an X.509 certificate from an issuer (a CA). The SSH Server uses a certificate only for FTPS, where it is used to authenticate the server to the FTPS client.
In Bitvise SSH Client:
Ssh Public Key Authentication Failed Unable To Extract Public Key From Private Key File
Public keys of hosts you have connected to can be viewed in Host key manager. When you connect to an SSH server for the first time, and the client has no record of the server's host key, the client will display the server's host key fingerprint, and will ask you to verify the key. It is very important to verify the server's host key fingerprint at this point, which should be done against a fingerprint you received through other means from the server's administrator. If you verify that the key is correct, the client will save it, and trust it for further connections to the server.
If you do not verify the server's host key, then the client cannot verify that the server you are connecting to is in fact the server you think you are connecting to. Not verifying the server's host key enables a man-in-the-middle attack - a situation where you aren't actually connecting to the server you think you are connecting to, but rather to another server that impersonates you to the destination server, and the destination server to you. Such a man-in-the-middle is able to observe all data sent over the SSH session, as well as modify what's being sent in real time. The only way to defend against such an attack is to make sure to verify the server's host key.
Private keys used for client authentication can be generated, imported and exported in User keypair manager. This interface allows you to generate a keypair for client authentication; you should keep the private key that's part of this keypair private. You can use the Export function to export the public key portion of a keypair, and send it to a server administrator, who can import it to allow you to authenticate using that key. The only thing you need to send to the server administrator is the public key; you should never send the private key, or the whole keypair.
Comments are closed.