Create a self-signed Certificate authority
Create an RSA key
Use the genrsa
command to create the server private key with the following properties:
- The key is protected with the symetric AES256 algorithm. (protecting the key is not mandatory)
- The key is
2048
bits long.
Here is the command:
$ openssl genrsa -aes256 -out private/server.key 2048
Generating RSA private key, 2048 bit long modulus
...............................................................................................+++
..+++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase for test.key: ********
Verifying - Enter pass phrase for test.key: ********
This create server.key
file. We can view informations about the generated key with the rsa
command:
$ openssl rsa -in private/server.key -text -noout
Enter pass phrase for test.key:
Private-Key: (2048 bit)
modulus:
00:c5:01:57:03:b1:11:5a:b8:3e:38:5e:ac:4e:27:
3f:40:79:f6:34:06:74:b5:4d:ad:48:4c:f3:02:22:
e2:f6:74:21:c0:72:63:ad:b6:f4:61:46:16:06:ef:
40:e3:80:5b:e8:d7:4e:44:d8:22:7c:51:ca:4c:e3:
f0:00:19:e1:a1:60:8e:18:e6:4d:14:96:91:58:5e:
4c:a6:4f:76:4e:98:d2:c2:4a:92:90:fc:be:73:d8:
49:4a:fb:35:c7:ba:38:8e:9f:65:8f:48:b9:d0:04:
00:c6:9a:44:9a:c2:6b:82:5e:d7:21:e9:da:86:1d:
1e:83:d0:4a:8e:20:93:90:d6:dc:d0:c2:96:a4:e9:
16:66:08:25:30:47:d5:4f:e9:14:a6:5f:94:c1:9f:
24:01:af:6d:f9:7c:54:98:11:62:2d:e6:e9:3b:8c:
b5:78:1f:26:96:bf:de:63:ed:d4:9d:52:7f:91:e4:
d7:9e:57:43:0b:29:ea:8b:e3:10:33:f2:4b:c0:b3:
e4:61:f7:5b:90:e8:9c:9c:fe:97:19:6e:5c:e8:90:
98:d7:d9:19:23:94:19:52:88:ca:3b:9c:70:92:a5:
8c:ba:cf:5d:54:2c:0f:fc:98:2a:ab:fb:c5:4f:88:
7f:a2:e1:39:72:da:b9:0d:2d:11:f3:03:9f:22:9c:
5f:1b
publicExponent: 65537 (0x10001)
privateExponent:
47:2b:a0:bf:d8:ac:28:55:ff:44:66:0f:61:7c:94:
41:3a:ce:53:25:31:ec:7d:cf:68:1b:44:7f:35:13:
41:6d:da:f3:a7:5f:93:56:51:1b:03:32:d9:f6:7d:
3e:b3:14:81:1d:a7:4c:ff:b8:15:a9:86:a8:18:80:
[ ... ]
Add the -pubout
parameter to output the public key:
$ openssl rsa -in private/server.key -pubout -out server.key.pub
It is also possible to create the key when creating a certificate signing request.
Create a server certificate signing request (csr
)
$ openssl req -new -key private/server.key -out server.csr
The signing request embbeds the public key:
$ openssl req -in server.csr -pubkey
and
$ openssl rsa -in private/server.key -pubout
give the same public key.
Create a csr
and the private key at the same time
$ openssl req -new \
-newkey rsa:2048 -nodes -keyout private_key.pem \
-out csr.pem \
-subj "/C=GB/ST=Yorks/L=York/O=MyCompany Ltd./OU=IT/CN=mysubdomain.mydomain.com" \
-addext 'subjectAltName=DNS:blog.quicheaters.org'
- the private key is in
private_key.pem
- the private key is NOT encrypted (
nodes
) - the private key is a 2048bits rsa key
- the
csr
is incsr.pem
- the
csr
has the subject:/C=GB/ST=Yorks/L=York/O=MyCompany Ltd./OU=IT/CN=mysubdomain.mydomain.com
- the
addext
allows to add extensions without having to update a configuration file
Create a self-signed certificate (generaly for Root-CA)
$ openssl req -new -x509 \
-newkey rsa:2048 -keyout ca_private_key.pem \
-extensions v3_ca -days 365 -out root_ca.pem
-x509
parameter is to output a self signed certificate instead of a certificate request-extensions v3_ca
use v3_ca extension as specified in your openssl.conf file-days
specify the number of days the certificate will be valid (365 days)
In my current configuration file the v3_ca
extension is:
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
Display certificate extentions
$ openssl x509 -purpose -in root_ca.pem
Certificate purposes:
SSL client : Yes
SSL client CA : Yes
SSL server : Yes
SSL server CA : Yes
Netscape SSL server : Yes
Netscape SSL server CA : Yes
S/MIME signing : Yes
S/MIME signing CA : Yes
S/MIME encryption : Yes
S/MIME encryption CA : Yes
CRL signing : Yes
CRL signing CA : Yes
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : Yes
Sign a certificate request with the self signed CA
$ openssl x509 -req \
-in req.csr \
-extensions v3_usr \
-CA root_ca.pem -CAkey ca_private_key.pem \
-CAcreateserial
On my system, the content of the v3_usr
extension is:
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
On important thing to note is that here, the extensions that have been set during the creation of the CSR are not applied to the final certificate when signed by the CA.
If you want to also add the extension, you must specify them again
during the signing phase. Either by updating the v3_usr
section, or
by specifiying then on the command line (in that case, the default
configuration file is ignored):
$ openssl x509 -req \
-in req.csr \
-extensions v3_usr \
-CA root_ca.pem -CAkey ca_private_key.pem \
-CAcreateserial
-extfile <(echo 'basicConstraints = CA:FALSE';
echo 'keyUsage = nonRepudiation, digitalSignature, keyEncipherment';
echo 'authorityKeyIdentifier=keyid,issuer';
echo 'subjectAltName=DNS:blog.quicheaters.org')
Viewing certificate information
This is done using the x509
command:
$ openssl x509 -in RapidSSLCA.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 145105 (0x236d1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA
Validity
Not Before: Feb 19 22:45:05 2010 GMT
Not After : Feb 18 22:45:05 2020 GMT
Subject: C=US, O=GeoTrust, Inc., CN=RapidSSL CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:c7:71:f8:56:c7:1e:d9:cc:b5:ad:f6:b4:97:a3:
fb:a1:e6:0b:50:5f:50:aa:3a:da:0f:fc:3d:29:24:
43:c6:10:29:c1:fc:55:40:72:ee:bd:ea:df:9f:b6:
41:f4:48:4b:c8:6e:fe:4f:57:12:8b:5b:fa:92:dd:
5e:e8:ad:f3:f0:1b:b1:7b:4d:fb:cf:fd:d1:e5:f8:
e3:dc:e7:f5:73:7f:df:01:49:cf:8c:56:c1:bd:37:
e3:5b:be:b5:4f:8b:8b:f0:da:4f:c7:e3:dd:55:47:
69:df:f2:5b:7b:07:4f:3d:e5:ac:21:c1:c8:1d:7a:
e8:e7:f6:0f:a1:aa:f5:6f:de:a8:65:4f:10:89:9c:
03:f3:89:7a:a5:5e:01:72:33:ed:a9:e9:5a:1e:79:
f3:87:c8:df:c8:c5:fc:37:c8:9a:9a:d7:b8:76:cc:
b0:3e:e7:fd:e6:54:ea:df:5f:52:41:78:59:57:ad:
f1:12:d6:7f:bc:d5:9f:70:d3:05:6c:fa:a3:7d:67:
58:dd:26:62:1d:31:92:0c:79:79:1c:8e:cf:ca:7b:
c1:66:af:a8:74:48:fb:8e:82:c2:9e:2c:99:5c:7b:
2d:5d:9b:bc:5b:57:9e:7c:3a:7a:13:ad:f2:a3:18:
5b:2b:59:0f:cd:5c:3a:eb:68:33:c6:28:1d:82:d1:
50:8b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
6B:69:3D:6A:18:42:4A:DD:8F:02:65:39:FD:35:24:86:78:91:16:30
X509v3 Authority Key Identifier:
keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 CRL Distribution Points:
URI:http://crl.geotrust.com/crls/gtglobal.crl
Authority Information Access:
OCSP - URI:http://ocsp.geotrust.com
Signature Algorithm: sha1WithRSAEncryption
ab:bc:bc:0a:5d:18:94:e3:c1:b1:c3:a8:4c:55:d6:be:b4:98:
f1:ee:3c:1c:cd:cf:f3:24:24:5c:96:03:27:58:fc:36:ae:a2:
2f:8f:f1:fe:da:2b:02:c3:33:bd:c8:dd:48:22:2b:60:0f:a5:
03:10:fd:77:f8:d0:ed:96:67:4f:fd:ea:47:20:70:54:dc:a9:
0c:55:7e:e1:96:25:8a:d9:b5:da:57:4a:be:8d:8e:49:43:63:
a5:6c:4e:27:87:25:eb:5b:6d:fe:a2:7f:38:28:e0:36:ab:ad:
39:a5:a5:62:c4:b7:5c:58:2c:aa:5d:01:60:a6:62:67:a3:c0:
c7:62:23:f4:e7:6c:46:ee:b5:d3:80:6a:22:13:d2:2d:3f:74:
4f:ea:af:8c:5f:b4:38:9c:db:ae:ce:af:84:1e:a6:f6:34:51:
59:79:d3:e3:75:dc:bc:d7:f3:73:df:92:ec:d2:20:59:6f:9c:
fb:95:f8:92:76:18:0a:7c:0f:2c:a6:ca:de:8a:62:7b:d8:f3:
ce:5f:68:bd:8f:3e:c1:74:bb:15:72:3a:16:83:a9:0b:e6:4d:
99:9c:d8:57:ec:a8:01:51:c7:6f:57:34:5e:ab:4a:2c:42:f6:
4f:1c:89:78:de:26:4e:f5:6f:93:4c:15:6b:27:56:4d:00:54:
6c:7a:b7:b7
Checking server certificate
This is done using the s_client
command:
$ openssl s_client -connect www.google.com:443
CONNECTED(00000003)
depth=1 /C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer=/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
---
No client certificate CA names sent
---
SSL handshake has read 1772 bytes and written 307 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-SHA
Session-ID: BDE08AD29E65CA4007711610FDD69165F9EB47065716D9AB469DAD9882E6E207
Session-ID-ctx:
Master-Key: 6FE2F273ABAAACF8E99180AAB9D540708F6A392DE1285787121B8A438E68FB3D01C127B31CC39146741D3A8396E0FA79
Key-Arg : None
Start Time: 1311928772
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
Things to note:
- The server’s certificate is enclosed by
-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
, this can be saved in a separate file for later reuse. - The Certificate name, the
Subject
is/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com.
- The Issuer of the certificate, ie the one who signed the certificate, is
/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
. - We were unable to check the validity of this certificate (
unable to get local issuer certificate
) because we do not have theIssuer
certifcate.
By giving the -CAfile
parameter we can give the CA certificate file of the CA who issued the server certificate. Here I guessed the CA certificate file from the Issuer
name:
$ openssl s_client -connect www.google.com:443 -CAfile /etc/ssl/certs/Verisign_Class_3_Public_Primary_Certification_Authority.pem
CONNECTED(00000003)
depth=2 /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
verify return:1
depth=1 /C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
verify return:1
depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
verify return:1
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
[ ... ]
SSL-Session:
Protocol : TLSv1
Cipher : RC4-SHA
Session-ID: 222E7CFF6DE8425B1B3635F706CDD65083F2758C87095D70E448E27C8272E377
Session-ID-ctx:
Master-Key: B04EBA908A928D7EF7B9432771A0C95A78BA060FBB75383AA081DDF8F8AD31A2F95CD0EF63AC09827A3220E7856EFE28
Key-Arg : None
Start Time: 1311929265
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
The server certificate is now considered as valid.
It is not always possible to guess the CA certificate filename, instead use the -CApath
to give the directory where resides all the known CA certificates of your system:
$ openssl s_client -connect www.google.com:443 -CApath /etc/ssl/certs/
[ ... ]
Verify return code: 0 (ok)
---
How to create a certificate chain ?
A certificate chain is just a file where multiple PEM
files are concatened. PEM
files must be ordered from the last certificate (for example server certificate or client certificate)
to the top Root CA..
$ cat server_crt.pem operational_ca.pem intermetiade_ca.pem root_ca.pem > certificate_chain.pem
Converting a .pem certificate to pkcs12
PKCS12 is a format to store a certficate AND it’s private key. Because it contains the private key, it needs to by encrypted. Unlike .pem file, the pkcs12 format is binary. So you cannot include it in text configuration files; it need to be base64 if needed.
$ openssl pkcs12 -export \
-in "blog.quicheaters.org.pem"
-inkey "blog.quicheaters.org.key" \
-out "blog.quicheaters.org.p12" \
-password 'pass:XXXxxxXXX' \
-certfile "CA/root-ca.pem"
New Apple requirements
For its newer iOS and macOS Operating Systems, Apple is enforcing new requirements for certificates. See https://support.apple.com/en-us/HT210176.
Here are ways to create Apple compatible certificates.
I’m using this small openssl configuration file:
$ cat openssl.cnf
[ req ]
distinguished_name = req
Create a self-signed CA
openssl req -config ./openssl.cnf \
-new -x509 -days 3650 -newkey rsa:4096 \
-keyout CA/-ca.key \
-passout pass:my_secret_pass \
-out CA/ca.pem \
-subj "/C=FR/ST=Ile de France/L=Parise/O=SuperCompany/CN=SuperCompany CA" \
-addext 'basicConstraints=critical,CA:true' \
-addext 'subjectKeyIdentifier=hash' \
-addext 'authorityKeyIdentifier=keyid:always,issuer:always' \
-addext 'keyUsage=critical,cRLSign,digitalSignature,keyCertSign'
Create a Server Certificate Signing Request
openssl req -config ./openssl.cnf \
-new -newkey rsa:4096 -nodes \
-keyout private/vpn.key \
-out certreqs/vpn.csr \
-subj "/C=FR/ST=Ile de France/L=Paris/O=SuperCompany/CN=vpn.example.com" \
-addext 'basicConstraints=critical,CA:FALSE' \
-addext 'subjectKeyIdentifier=hash' \
-addext 'keyUsage=critical,nonRepudiation,digitalSignature,keyEncipherment,keyAgreement' \
-addext 'extendedKeyUsage=critical,serverAuth' \
-addext 'subjectAltName=DNS:vpn.example.com,IP:1XX.XX.XX.23'
Sign the Certificate Request
openssl x509 \
-req -in certreqs/vpn.csr \
-CA CA/ca.pem -CAkey CA/ca.key -CAcreateserial \
-passin pass:my_secret_pass \
-days 825 \
-out newcerts/vpn.pem \
-extfile <(echo 'basicConstraints=critical,CA:FALSE';
echo 'subjectKeyIdentifier=hash';
echo 'authorityKeyIdentifier=keyid:always,issuer:always';
echo 'keyUsage=critical,nonRepudiation,digitalSignature,keyEncipherment,keyAgreement';
echo 'extendedKeyUsage=critical,serverAuth';
echo 'subjectAltName=DNS:vpn.example.com,IP:1XX.XX.XX.23';)