Certificates

Certificates are essentially keys, which have been certified by another party, that those keys indeed belong to a person or device.

Certificates signed by commercial certificate authorities are usually created directly on their website using built-in functions of web-browsers which require minimal interaction from the user.

Here we will manually create a CSR to be signed by a certification authority.

Preparations

Create a personal directory to store configuration, keys, CSR and certificates:

$ mkdir -p ~/.ssl/{certs,private}
$ chmod 700 ~/.ssl/private

Set some environment variables:

$ export CN=$HOSTNAME.example.net
$ export emailAddress=john.doe@example.net

Personal User Certificate Request

Personal certificates may be used to login on websites and to sign and encrypt email. They include information about a person.

OpenSSL Configuration

Create a new OpenSSL configuration file ~/.ssl/openssl-user.cnf:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#
# OpenSSL configuration for generation of client certificate requests.
#
# Environment variables 'emailAddress' **MUST** be defined or else
# OpenSSL aborts:
#    export emailAddress=user@example.net
#
# To use this configuration as default:
#    export OPENSSL_CONF=./openssl-user.cnf
#

emailAddress    = $ENV::emailAddress
HOME            = $ENV::HOME/.ssl
RANDFILE        = $HOME/private/.rnd
oid_section     = new_oids

[ new_oids ]
xmppAddr = 1.3.6.1.5.5.7.8.5

[ req ]
default_bits        = 2048
default_keyfile     = $HOME/private/$emailAddress.key.pem
encrypt_key         = yes
default_md          = sha256
req_extensions      = user_req_ext
prompt              = no
distinguished_name  = req_distinguished_name
string_mask         = utf8only
utf8                = yes

[ user_req_ext ]
keyUsage                = digitalSignature
extendedKeyUsage        = clientAuth, emailProtection
subjectKeyIdentifier    = hash
subjectAltName          = @subj_alt_names

[ req_distinguished_name ]
countryName             = US
stateOrProvinceName     = California
localityName            = Los Angeles
organizationName        = example.net
Name                    = John Doe
emailAddress            = $emailAddress

[ subj_alt_names ]
email       = $emailAddress
otherName   = xmppAddr;UTF8:$emailAddress

Change the highlighted lines to your needs.

Make the configuration the default to use by OpenSSL:

$ export OPENSSL_CONF=~/.ssl/openssl-user.cnf

Certificate Signing Request

Create the personal certificate request and key:

$ openssl req -new -out ~/.ssl/$emailAddress.req.pem
Generating a 2048 bit RSA private key
.......................................+++
...............................+++
writing new private key to '/home/john/.ssl/john.doe@example.net.key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

Protect the private key:

$ chmod 400 ~/.ssl/private/$emailAddress.key.pem

Take a peek in the request:

$ openssl req -verify -in ~/.ssl/$emailAddress.req.pem \
    -noout -text -nameopt multiline \
    -reqopt no_version,no_pubkey,no_sigdump

Send the file ~/.ssl/john.doe@example.net.req.pem to the CA for signing.

Client Device Certificate

Client host certificates may be used to identify a particular device. I.e. to establish a connection to a VPN service. They might also include information about its owner.

In todays connected world, mobile devices are lost and stolen every day. By using certificates for devices instead of its owners, a single lost or stolen device can be locked out, without affecting other devices of the same person.

OpenSSL Configuration

Create a new OpenSSL configuration file ~/.ssl/openssl-client.cnf:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#
# OpenSSL configuration for generation of client certificate requests.
#
# To use this configuration as default:
#    export OPENSSL_CONF=./openssl-client.cnf
#
# Environment variables '$CN' and 'emailAddress' **MUST** be defined or else
# OpenSSL aborts:
#    export CN=${HOSTNAME}.example.net
#    export emailAddress=user@example.net
#

emailAddress         = $ENV::emailAddress
CN                   = $ENV::CN
HOME                 = $ENV::HOME/.ssl
RANDFILE             = $HOME/private/.rnd
oid_section          = new_oids

[ new_oids ]
id-on-xmppAddr       = 1.3.6.1.5.5.7.8.5

[ req ]
default_bits          = 2048
default_keyfile       = $HOME/private/$CN.key.pem
encrypt_key           = yes
default_md            = sha256
req_extensions        = device_req_ext
prompt                = no
distinguished_name    = req_distinguished_name
string_mask           = utf8only
utf8                  = yes

[ device_req_ext ]
keyUsage              = digitalSignature
extendedKeyUsage      = clientAuth
subjectKeyIdentifier  = hash
subjectAltName        = @subj_alt_names

[ req_distinguished_name ]
countryName           = US
stateOrProvinceName   = California
localityName          = Los Angelees
commonName            = $CN
name                  = John Doe
emailAddress          = $emailAddress

[ subj_alt_names ]
DNS.1                 = $CN
email                 = $emailAddress
otherName             = xmppAddr;UTF8:$emailAddress

Change the highlighted lines to your needs.

Make the configuration the default to use by OpenSSL:

$ export OPENSSL_CONF=~/.ssl/openssl-client.cnf

Certificate Signing Request

Create the client device request:

$ openssl req -new -out ~/.ssl/$CN.req.pem
Generating a 2048 bit RSA private key
.......................................+++
...............................+++
writing new private key to '/home/john/.ssl/host.example.net.key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

Protect the private key:

$ chmod 400 ~/.ssl/private/$CN.key.pem

Take a peek in the request:

$ openssl req  -verify -in ~/.ssl/$CN.req.pem \
    -noout -text \
    -reqopt no_version,no_pubkey,no_sigdump \
    -nameopt multiline

Send the file ~/.ssl/host.example.net.req.pem to the CA for signing.

Using the Certificate

After the CA has verified and signed the certificate singing request you get a the certificate in a file like host.example.net.cert.pem.

To view the certificate:

$ openssl x509 -in $CN.cert.pem \
    -noout -text \
    -certopt no_version,no_pubkey,no_sigdump \
    -nameopt multiline

To verify the certificate:

$ openssl verify -issuer_checks -policy_print -verbose \
    -untrusted intermed-ca.cert.pem \
    -CAfile root-ca.cert.pem \
    certs/$CN.cert.pem