5

I have a configuration as below in my ~/.ssh/config file:

Host xxx
    HostName 127.0.0.1
    Port 2222
    User gigi
    ServerAliveInterval 30
    IdentityFile ~/blablabla
    # CertificateFile ~/blablabla-cert.pub

which works fine but I'm curious about how would one generate the CertificateFile if really wants to use it? Consider one already has the private and public RSA keys generated with e.g. openssl req -newkey rsa:2048 -x509 [...].

Adrian
  • 701
  • 1
  • 8
  • 29
  • I'm a bit confused here - are you mixing up SSH keys and SSL certificates? If so, you'll want to take a look at this: https://security.stackexchange.com/q/32768/112299 – Haxiel Mar 02 '19 at 06:31
  • frankly speaking I don’t know; I realized that I don’t fully understand the purpose of CertificateFile when used in this context; I suppose it’s just an additional check when a client tries to connect to a ssh server but I might be wrong. Anyway, the question is still valid despite of my lack of understanding. – Adrian Mar 02 '19 at 06:49

2 Answers2

8

The certificate model of authentication used by SSH is a variation of the public key authentication method. With certificates, each user's (or host's) public key is signed by another key, known as the certificate authority (CA). The same CA can be used to sign multiple user or host keys. The user or the host can then trust a single CA instead of having to trust each individual user/host key. Because this is a change in the authentication model, implementing certificates requires changes on both the client and the server side.

Also, do note that the certificates used by SSL (the ones generated by openssl) are different from the ones used by SSH. This topic is explained by these QAs at the Security SE: What is the difference between SSL & SSH?, Converting keys between OpenSSL and OpenSSH.

Now, since the question is about how a client could connect to a server using an SSH certificate, let's look at that approach. The manual page for ssh-keygen has some relevant information:

ssh-keygen supports signing of keys to produce certificates that may be used for user or host authentication. Certificates consist of a public key, some identity information, zero or more principal (user or host) names and a set of options that are signed by a Certification Authority (CA) key. Clients or servers may then trust only the CA key and verify its signature on a certificate rather than trusting many user/host keys. Note that OpenSSH certificates are a different, and much simpler, format to the X.509 certificates used in ssl(8).

ssh-keygen supports two types of certificates: user and host. User certificates authenticate users to servers, whereas host certificates authenticate server hosts to users. To generate a user certificate:

$ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub

The resultant certificate will be placed in /path/to/user_key-cert.pub.

A host certificate requires the -h option:

$ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub

The host certificate will be output to /path/to/host_key-cert.pub.

The first thing we'll need here is a CA key. A CA key is a regular private-public key pair, so let's generate one as usual:

ssh-keygen -t rsa -f ca

The -f ca option simply specifies the output filename as 'ca'. This results in the two files being generated - ca (private key) and ca.pub (public key).

Next, we'll sign our user key with the CA's private key (following the example from the manual):

ssh-keygen -s path/to/ca -I myuser@myhost -n myuser ~/.ssh/id_rsa.pub

This will generate a new file named ~/.ssh/id_rsa-cert.pub which contains the SSH certificate. The -s option specifies the path to the CA private key, the -I option specifies an identifier that is logged at the server-side, and the -n option specifies the principal (username). The contents of the certificate can be verified by running ssh-keygen -L -f ~/.ssh/id_rsa-cert.pub.

At this point, you're free to edit your configuration file (~/.ssh/config) and include the CertificateFile directive to point to the newly generated certificate. As the manual indicates, the IdentityFile directive must also be specified along with it to identify the corresponding private key.

The last thing to do is to tell the server to trust your CA certificate. You'll need to copy over the public key of the CA certificate to the target server. This is done by editing the /etc/ssh/sshd_config file and specifying the TrustedUserCAKeys directive:

TrustedUserCAKeys /path/to/ca.pub

Once that is done, restart the SSH daemon on the server. On my CentOS system, this is done by running systemctl restart sshd. After that, you will be able to log in to the system using your certificate. Tracing your ssh connection using the verbose flag (-v) will show the certificate being offered to the server and the server accepting it.

One last thing to note here is that any user key signed with the same CA key will now be trusted by the target server. Access to the CA keys must be controlled in any practical scenario. There are also directives such as AuthorizedPrincipalsFile that can be used to limit the access from the server side. See the manual for sshd_config for more details. On the client side, the certificates can also be created with tighter specifications. See the manual for ssh-keygen for those details.

Haxiel
  • 8,361
  • This is a great summation. I'd like to add that a line with the contents of ca.pub should go into myuser/.ssh/known_hosts formatted with the preceeding directive @cert-authority *. This negates the message The authenticity of host... upon first connect to host. – Nstevens Jun 25 '22 at 13:33
0

To convert your .crt to .pub just do this:

  1. Extract the public key

    openssl x509 -in CERT.crt -pubkey -noout > CERT.pub.tmp
    
  2. Convert to a SSH format (PKCS8)

    ssh-keygen -f CERT.pub.tmp -i -m PKCS8 > CERT.pub
    
Pablo A
  • 2,712