Using OpenSSH Certificates for Host Login
OpenSSH supports a proprietary version of certificates that allow simple login to hosts.
The usual way to enable a user
U to access a specific host
H using SSH is to copy the public key of
U in a file on
H (typically called
This method suffers from a lack of generality. If another user
U' were to be given access to
H, their public key should also be copied in that same file. At the same time, if
U were to be given access to a different host
H', their public key would have to be added to an equivalent file on that host.
While various automatic provisioning systems have been devised, those still represent a workaround rather than a solution to the problem.
Since version 5.4 (released 2010-03-08) OpenSSH has had support for so-called OpenSSH Certificates.
By using these, only one OpenSSH CA public key has to be copied onto the target host. At that point any user can be granted access to any such host by giving them a file that contains the following information: their own public key, a validity period, a list of usernames that the user is allowed to login as, and a digital signature over the whole content created using the private key of an SSH CA.
This file, the SSH Certificate, is then automatically presented to the SSH server by the SSH client of the user as part of the login process.
OpenSSH Certificates with YubiHSM 2
The private key of an SSH CA is a regular private key and can be stored on a YubiHSM 2. OpenSSH has built-in support for signing SSH Certificates using CA private keys that reside on a hardware token through the PKCS#11 interface.
The YubiHSM 2 also has specific support for signing SSH Certificates using an RSA CA key. This guide will also describe how to leverage that.
Example: OpenSSH built-in support for Signing SSH certificates
Signing SSH certificates is performed with OpenSSH’s
ssh-keygen command using the
-s ca_key option. The
ca_key specifies the key file containing the signing key. The signing key can be stored in an HSM, in which case the key file only contains the public part of the signing key. The public key is used to locate the corresponding private key on the HSM through the PKCS#11 interface. The PKCS#11 module to use is specified with the
Create an SSH CA key on the HSM, export the CA public key, and convert the public key into PKCS8 format for use with OpenSSH.
$ yubihsm-shell -a generate-asymmetric-key --authkey=0x0001 -p password -i 0x000a -l "SSH_CA_Key" -c "sign-pkcs" -A rsa2048 Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1 Generated Asymmetric key 0x000a $ yubihsm-shell -p password --authkey=0x0001 -a get-public-key -i 0x000a --out ca_pub.pem Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1 $ ssh-keygen -i -f ca_pub.pem -m PKCS8 > ca.pub
The CA key needs capability
Sign the user’s pubkey in the file
$ ssh-keygen -s ca.pub -D /usr/local/lib/pkcs11/yubihsm_pkcs11.dylib -I key_id id_rsa.pub Enter PIN for 'YubiHSM': Signed user key id_rsa-cert.pub: id "key_id" serial 0 valid forever
The PIN needs to be prefixed with the ID of the authentication-key in order for
The signed SSH certificate is generated in the file
Signing SSH Certificate Requests
Instead of directly signing a user’s SSH pubkey directly, the YubiHSM 2 can also be used to sign SSH pubkeys only when a number of conditions are met. This scenario is discussed in the rest of this document.
High-level Description and components
A YubiHSM 2 device is able to sign OpenSSH public keys when those are submitted to the device as part of a specific format that we call
OpenSSH Certificate Request.
Such a request is granted (i.e. the signature is computed and released), if and only if the following two requirements are fulfilled:
The user who sends the request to the device has the right privileges to access the OpenSSH CA private key on the device.
This is fulfilled by making sure that the user submitting the request (who may not be the same one who generates the request) can establish a Session with the device through an Authentication Key that has access to the necessary Domains and has the necessary Capability set.
The OpenSSH Certificate Request meets a series of pre-defined constraints.
This is fulfilled by encoding those pre-defined constraints in an object with Type
SSH Template is a binary object that can be used to restrict how and when an SSH CA private key should be used to sign SSH Certificate Requests.
This is a binary object that encodes a series of constraints. Its format is a collection of Tag-Length-Value tuples whose meaning is described below:
|Tag Value||Tag Description|
|0x01||Timestamp key algorithm|
|0x02||Timestamp public key|
|0x03||CA key white-list|
The individual tags are further explained below.
Timestamp Key Algorithm – The ALGORITHMS of the public key used to verify timestamp signatures.
Timestamp Public Key – The public key used to verify timestamp signatures.
CA Key White-list – The list of Object IDs describing which Asymmetric Keys can be used with this template.
Not Before – The Not Before time offset to be applied to the current time. If a request contains a time value that is before this computed timestamp, an error will be returned.
Not After – The Not After time offset to be applied to the current time. If a request contains a time value that is after this computed timestamp, an error will be returned.
Principals Black-list – The nul-separated, nul-terminated list of Principals (user names) for which a certificate will not be issued.
Example template – A hex-dump of an example template file is shown below:
01 0001 09 02 0100 cb2702...d71081f1d1 03 0002 000a 04 0004 000012c0 05 0004 00008ca0 06 0005 726f6f7400
This template file contains, in order:
- Timestamp Key Algorithm 9 (RSA 2048)
- Timestamp public key (256 bytes)
- CA Key whitelist containing the single Key ID 0x000a
- A Not before offset of 300 seconds (5 minutes)
- A Not before offset of 36000 seconds (10 hours)
- A principal blacklist containing the principal
Although not officially supported, templates can be generated using yubihsm-ssh-tool.
For instance, the above template file and the embedded timestamp key are generated using:
$ openssl genrsa -out timestamp.pem Generating RSA private key, 2048 bit long modulus .................................+++ ........................................+++ e is 65537 (0x10001) $ openssl rsa -pubout -in timestamp.pem -out timestamp_pub.pem writing RSA key $ pipenv run yubihsm-ssh-tool templ -T timestamp_pub.pem -k 10 -b 300 -a 36000 -p root
Here, the file
timestamp_pub.pem contains the timestamp certificate public key, the CA key ID is 10, certificates should only be issued if their validity is at most 5 minutes in the past (to accomodate for clock skew) and at most 10 hours in the future. Also, certificates for user
root are not allowed.
SSH Certificate Request
An SSH certificate format is defined by OpenSSH but it is not too dissimilar from an X.509 certificate. At its core it is a collection of attributes, a time period, a public key and a signature over all the data.
An SSH Certificate Request is the set of information that must be sent to a YubiHSM 2 so that it can generate the aforementioned signature. This consists of all the data present in the certificate (excluding the signature).
For a description, see the
email@example.com key format in the the OpenSSH specs.
Signing an SSH Certificate Request
After an SSH Template has been stored on the YubiHSM 2 and an SSH Certificate Request has been created, it can be sent to the device for signing.
This is done by issuing the Sign SSH Certificate Command. The parameters required are:
- Object ID of the SSH CA key which has already been stored on the device
- Object ID of the SSH Template to use in order to validate the request
- Algorithm to use to produce the certificate signature
- timestamp with the definition of
STover the SSH Certificate Request and the timestamp
- SSH Certificate Request
After the command is issued, the following steps take place in the YubiHSM 2. First the signature
ST is verified using the public key present within the specified SSH Template. If the verification is successful, the value of
Now is recorded. Next the SSH Certificate Request is parsed to extract the
Not Before and
Not After timestamps together with the list of Principals. The following checks are then performed:
- ID of the SSH CA key must appear in the SSH CA key white-list present in the SSH Template.
Not Beforetimestamp in the SSH Certificate Request must be greater than or equal to
Not Beforeoffset specified in the SSH Template.
Not Aftertimestamp in the SSH Certificate Request must be less than or equal to
Not Afteroffset specified in the SSH Template.
- That none of the Principals specified in the SSH Certificate Request must appear in the Principals black-list SSH Template.
If all the constraints were fulfilled, the YubiHSM 2 produces a signature using the Algorithm specified in the command. This signature can be appended to the SSH Certificate Request to produce a valid SSH Certificate.
Although not officially supported, requests can be generated using yubihsm-ssh-tool:
$ pipenv run yubihsm-ssh-tool req -s ca_pub.pem -t timestamp.pem -I user-identity -n username -V -5h:+5h id_rsa.pub
Example: Signing SSH certificates using templates and signing requests
Below is an example of signing SSH certificates using templates and certificate requests.
Create an SSH CA key on the HSM, and export the CA public key.
$ yubihsm-shell -a generate-asymmetric-key --authkey=0x0001 -p password -i 10 -l "SSH_CA_Key" -c "sign-ssh-certificate" -A rsa2048 Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1 Generated Asymmetric key 0x000a $ yubihsm-shell -p password --authkey=0x0001 -a get-public-key -i 10 --out ca_pub.pem Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1
This time, the CA key needs capability
Create the template file and store the template in the HSM as an object of type
$ pipenv run yubihsm-ssh-tool templ -T timestamp_pub.pem -k 10 -b 36000 -a 36000 -p root $ yubihsm-shell -a put-template -p password -i 20 -l "SSH_Template" -A template-ssh --in templ.dat Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1 Stored Template object 0x0014
Generate a certificate signing request for user
$ pipenv run yubihsm-ssh-tool req -s ca_pub.pem -t timestamp.pem -I user-identity -n username -V -5h:+5h id_rsa.pub Hash is: b'95dd317189b5e392481de896e7f111228b76d6efe3daa344c2da28 19927a05cb'
Sign the certificate request using the CA key on the HSM.
$ yubihsm-shell -a sign-ssh-certificate -p password -i 10 --template-id 20 -A rsa-pkcs1-sha256 --in req.dat --out id_rsa-cert.pub Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1
The signed SSH certificate is generated in the file
Example: constraint violation
To illustrate what happens when the constraints specified in the certificate template are violated, for instance when a certificate is requested for the
$ pipenv run yubihsm-ssh-tool req -s ca_pub.pem -t timestamp.pem -I user-identity -n root -V -5h:+5h id_rsa.pub Hash is: b'b75d30392a5ea5887affceb593154d2cc860f76f7bbc82757ec3fa20cd2a4d63' $ yubihsm-shell -a sign-ssh-certificate -p password -i 10 --template-id 20 -A rsa-pkcs1-sha256 --in req.dat --out id_rsa-cert.pub Using default connector URL: http://127.0.0.1:12345 Session keepalive set up to run every 15 seconds Created session 1 Failed to get certificate signature: SSH CA constraint violation Unable to get ssh certificate