# [HOWTO] SSH & X509 certificates

## eunuque

Hi all,

I have not seen any "simple" documentation explaining how to enable X509 certificates for SSH keys.

The author of the X509 patch for OpenSSH provides usefull information on this webpage:

http://roumenpetrov.info/openssh/x509-5.3/README.x509v3

But you need to have a good knowledge of OpenSSL to have it work!

So here is my documentation for dummy gentoo users...   :Wink: 

1/ Introduction

There are no standard way of managing SSH keys. You can always exchange a user or host key with

one of your friends and check the fingerprint together, but what if you want to be sure of the

authenticity of hundreds of keys?

X509 certificates could be a solution: keys are signed by a Certification Authority (CA).

Then what you check is only this signature instead of SSH public keys.

In this guide we will assume that user toto from client foo wants to authenticate against SSH server bar.

Our OpenSSL PKI will be installed on foo.

2/ Emerge OpenSSH

```
[root@foo]$ USE="X509 -ldap" emerge openssh

[root@bar]$ USE="X509 -ldap" emerge openssh
```

Note I tested with openssh ebuild 4.3_p2-r1.

3/ Create a PKI

```
[root@foo]$ emerge openssl (if not already installed)

[root@foo]$ mkdir /opt/LocalCA

[root@foo]$ cd  /opt/LocalCA

[root@foo]$ mkdir certs

[root@foo]$ mkdir conf

[root@foo]$ mkdir private

[root@foo]$ chmod 700 private

[root@foo]$ echo '01' > serial

[root@foo]$ touch index.txt
```

Edit /opt/LocalCA/conf/fooCA.cnf:

A template can be found at http://sapiens.wustl.edu/~sysmain/info/openssl/LocalCA

You may just change the [ root_ca_distinguished_name ] section to match your data.

This file will be used to generate our CA certificate in .pem format:

```
[root@foo]$ cd /opt/LocalCA

[root@foo]$ export OPENSSL_CONF=/opt/LocalCA/conf/fooCA.cnf

[root@foo]$ openssl req -x509 -newkey rsa -out cacert.pem -outform PEM -days 1825
```

3/ Client configuration

On foo client, we need to sign our ssh keys. We will save the configuration request in /opt/LocalCA/conf/too@foo.cnf:

```
[ ca ]

default_ca      = local_ca

[ local_ca ]

dir             = /opt/LocalCA

certificate     = $dir/cacert.pem

database        = $dir/index.txt

new_certs_dir   = $dir/certs

private_key     = $dir/private/cakey.pem

serial          = $dir/serial

default_crl_days        = 365

default_days            = 1825

default_md              = md5

policy          = local_ca_policy

[ local_ca_policy ]

commonName              = supplied

#stateOrProvinceName    = supplied

countryName             = supplied

emailAddress            = supplied

organizationName        = supplied

#organizationalUnitName = supplied

[ req ]

default_md      = md5

prompt                  = no

distinguished_name      = toto_distinguished_name

x509_extensions         = usr_cert

[ toto_distinguished_name ]

commonName              = toto tutu

countryName             = FR

emailAddress            = toto@mycompany.com

organizationName        = mycompany

[ usr_cert ]

basicConstraints                = CA:FALSE

nsCertType                      = client,email

nsComment                       = "OpenSSL Generated OpenSSH Client Certificate"

subjectKeyIdentifier            = hash

authorityKeyIdentifier          = keyid,issuer:always

[ srv_cert ]

basicConstraints                = CA:FALSE

nsCertType                      = server,client

nsComment                       = "OpenSSL Generated OpenSSH Server Certificate"

subjectKeyIdentifier            = hash

authorityKeyIdentifier          = keyid,issuer:always

```

Replace the [ toto_distinguished_name ] section by your data.

Now we request and sign a certificate, then update our SSH keys.

```

[toto@foo]$ cd ~/.ssh

[toto@foo]$ ssh-keygen -t rsa -b 1024 -f id_rsa -N ""

[toto@foo]$ export OPENSSL_CONF=/opt/LocalCA/conf/toto@foo.cnf

[toto@foo]$ openssl req -new -key id_rsa -out id_rsa.csr

[root@foo]$ openssl ca -in id_rsa.csr -out id_rsa.crt

[toto@foo]$ openssl x509 -in id_rsa.crt -subject -issuer -alias >> id_rsa

[toto@foo]$ ssh-keygen -y -f id_rsa > id_rsa.pub
```

Your id_rsa.pub key should now look like:

```
x509v3-sign-rsa XXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

....
```

4/ Server configuration

On server side, edit ~toto/.ssh/authorized_keys:

```
...

x509v3-sign-rsa subject= /CN=toto tutu/C=FR/emailAddress=toto@mycompany.com/O=mycompany

```

where subject= ... is the output of the following command:

```
openssl x509 -noout -subject -in id_rsa.crt
```

The sshd daemon also need to have the CA certificate to validate toto certificate:

copy cacert.pem from foo machine to the /etc/ssh/ca/crt/ directory on bar, then

```
[root@bar]$ cd /etc/ssh/ca/crt

[root@bar]$ ln -s cacert.pem HASH.0
```

where HASH is the output of the following command:

```
[root@bar]$ openssl x509 -in cacert.pem -noout -hash
```

5/ Test

Here we are!

Test ssh authentication with certificate:

```
[toto@foo]$ ssh bar
```

You should not be asked for any password and the ssh logs should indicate:

```
Mar  7 15:21:42 bar sshd[24496]: Accepted publickey for toto from 82.41.111.238 port 41271 ssh2

```

If it is not working, you may grab some usefull information there, like

'unable to get local issuer certificate' or whatever.

6/ Host certificates

You may use certificates with host keys. Just repeat step 3/ with your SSH host key (/etc/ssh/ssh_host_rsa_key).

On client side, you also need to copy the CA certificate(cacert.pem).

```
After accepting the new key, your known_hosts file should look like:

bar,82.41.111.222 x509v3-sign-rsa Subject: ...

```

----------

## di1bert

Hey Eunuque

That's a great HowTo you wrote. I've just started working with OpenSSH and X509 keys and yours is by far the best.

However I came across a little hiccup. I don't know if it's the version of Openssl I'm using (0.9.8d) but your line:

```

openssl req -x509 -newkey rsa -out cacert.pem -outform PEM -days 1825

```

wouldn't work until you added the bit size to the RSA option so it now looks like this:

```

openssl req -x509 -newkey [b]rsa:1024[/b] -out cacert.pem -outform PEM -days 1825

```

Other than that, great job. Thanks for the help   :Very Happy: 

----------

## gdibble

Eunuque, thank you for this guide  :Smile: 

I noticed the template link is dead.

Here is the last available copy:

 :Arrow:  http://web.archive.org/web/20060907064924/http://sapiens.wustl.edu/~sysmain/info/openssl/LocalCA

Kind regards, Gabriel

----------

## ciges

Thanks you very much @eunuque, your guide have been really usefull for me  :Smile: 

I have been struggling with authentication via SSH using X509 certificates, and after some time I have understood it and tested with success.

In case it's useful for anyone I have written a post explaining the full process on a blog I have just deployed (in a quick & dirty way, the blog is simple and not very pretty, but useful). You can read a full description of the test in the article "OpenSSH with X509 certificates HOW TO".

Regards.

----------

