In some cases, it is needed to create your chain of certificates - CA and server (for example TLS testing). There are many descriptions out there on how to do it, nevertheless, I couldn’t find any copy-paste examples which would give me an RSA, ECDSA and EdDSA certificates. Hence, here below, one can find some instructions on how to use openssl
to quickly create your certs which, then can then be used during TLS verification.
This post doesn’t explain meaning of configuration used. If such explenation is needed I would suggest reading “Network Security with OpenSSL: Cryptography for Secure Communications”, by J. Viega or looking for required information at this blog.
Configuration file
OpenSSL uses configuration file in order to store information required during certificate creation. Configuraiton file contains things like organization name, address, location, internet address, default hash algorithm used to produce signatures, etc.
Name of both - my example CA and an organization for which server certificate will be created - is called “Cert Testing Organization” with an address www.cert_testing.com
.
Here below configuration file used in this example. Copy & paste it to file openssl.cnf
:
1[ ca ]
2# `man ca`
3default_ca = CA_default
4
5[ CA_default ]
6# Directory and file locations.
7dir = .
8certs = $dir/certs
9crl_dir = $dir/crl
10new_certs_dir = $dir/newcerts
11database = $dir/index.txt
12serial = $dir/serial
13RANDFILE = $dir/private/.rand
14
15# The root key and root certificate.
16private_key = $dir/root.key
17certificate = $dir/root.pem
18
19# For certificate revocation lists.
20crlnumber = $dir/crlnumber
21crl = $dir/crl/intermediate.crl.pem
22crl_extensions = crl_ext
23default_crl_days = 30
24
25# SHA-1 is deprecated, so use SHA-2 instead.
26default_md = sha256
27
28name_opt = ca_default
29cert_opt = ca_default
30default_days = 9999
31preserve = no
32policy = policy_loose
33
34[ policy_strict ]
35# The root CA should only sign intermediate certificates that match.
36# See the POLICY FORMAT section of `man ca`.
37countryName = match
38stateOrProvinceName = match
39organizationName = match
40organizationalUnitName = optional
41commonName = supplied
42emailAddress = optional
43
44[ policy_loose ]
45# Allow the intermediate CA to sign a more diverse range of certificates.
46# See the POLICY FORMAT section of the `ca` man page.
47countryName = optional
48stateOrProvinceName = optional
49localityName = optional
50organizationName = optional
51organizationalUnitName = optional
52commonName = supplied
53emailAddress = optional
54
55[ req ]
56# Options for the `req` tool (`man req`).
57default_bits = 4096
58distinguished_name = req_distinguished_name
59string_mask = utf8only
60
61[ req_distinguished_name ]
62countryName = Country Name (2 letter code)
63stateOrProvinceName = State or Province Name (full name)
64localityName = Locality Name (eg, city)
65organizationalUnitName = Organizational Unit Name (eg, section)
66commonName = Common Name
67
68stateOrProvinceName_default = PACA
69countryName_default = FR
70localityName_default = Cagnes sur Mer
71organizationalUnitName_default = Cert Testing Organization
72commonName_default = Cert Testing Organization
73commonName_max = 64
74
75[ v3_ca ]
76# Extensions for a typical CA (`man x509v3_config`).
77subjectKeyIdentifier = hash
78authorityKeyIdentifier = keyid:always,issuer
79basicConstraints = critical, CA:true
80keyUsage = critical, digitalSignature, cRLSign, keyCertSign
81
82[ v3_intermediate_ca ]
83# Extensions for a typical intermediate CA (`man x509v3_config`).
84subjectKeyIdentifier = hash
85authorityKeyIdentifier = keyid:always,issuer
86basicConstraints = critical, CA:true, pathlen:0
87keyUsage = critical, digitalSignature, cRLSign, keyCertSign
88
89[ usr_cert ]
90# Extensions for client certificates (`man x509v3_config`).
91basicConstraints = CA:FALSE
92nsCertType = client, email
93nsComment = 'Cert Testing Intermediate - Client'
94subjectKeyIdentifier = hash
95authorityKeyIdentifier = keyid,issuer
96keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
97extendedKeyUsage = clientAuth, emailProtection
98
99[ server_cert ]
100# Extensions for server certificates (`man x509v3_config`).
101basicConstraints = CA:FALSE
102nsCertType = server
103nsComment = 'Cert Testing Intermediate - Server'
104subjectKeyIdentifier = hash
105authorityKeyIdentifier = keyid,issuer:always
106keyUsage = critical, digitalSignature, keyEncipherment
107extendedKeyUsage = serverAuth
108subjectAltName = @alt_names
109
110[ client_cert ]
111# Extensions for server certificates (`man x509v3_config`).
112basicConstraints = CA:FALSE
113nsCertType = client, email
114nsComment = 'Cert Testing EE - Client'
115subjectKeyIdentifier = hash
116authorityKeyIdentifier = keyid,issuer
117keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
118extendedKeyUsage = clientAuth, emailProtection
119
120[ crl_ext ]
121# Extension for CRLs (`man x509v3_config`).
122authorityKeyIdentifier = keyid:always
123
124[ ocsp ]
125# Extension for OCSP signing certificates (`man ocsp`).
126basicConstraints = CA:FALSE
127subjectKeyIdentifier = hash
128authorityKeyIdentifier = keyid,issuer
129keyUsage = critical, digitalSignature
130extendedKeyUsage = critical, OCSPSigning
131
132[alt_names]
133DNS.1 = *.cert_testing.com
134IP.1 = 127.0.0.1
Preparation
We will need some directories where output of cert generation will be stored:
CA cert creation
-
CA private key
First step is to create private key of CA cert. Root cert will use RSA keypair with key length of 4096 bits.
OpenSSL will ask for pasword - provide
test123
.openssl genrsa -aes256 -out private/ca.key 4096
or in case of ECDSA certificates:
openssl ecparam -name prime256v1 -genkey -noout -out private/ca.key openssl ec -in private/ca.key -out private/ca.key -aes256
Here second line (encrypting ca.key) is needed only for rest of the article to be copy-paste’able.
-
Create CA cert
This command will use a key created above and create self-signed CA certificate. Certificate will be valid for 9999 days.
Provide password
test123
and hit enter on everything else.openssl
will use values defined inopenssl.cnf
.openssl req -config openssl.cnf \ -extensions v3_ca -new -x509 -days 9999 \ -key private/ca.key \ -out certs/ca.cert
One interesting option to notice is
-extensions v3_ca
- it is reference to the section with the same name inopenssl.cnf
. This section tells theopenssl
that created certificate must be a CA cert (CA:true
).
Server cert creation
In this example, certificate signing is done in 3 steps.
- Create server certificate private key
- Create certificate singing request
- Sign the request with CA private key
So let’s do it.
-
Server’s private key (I skip intermediate certs creation for the brevity).
-
RSA/2048 with e=3, for fast verification
openssl genpkey -algorithm RSA \ -pkeyopt rsa_keygen_bits:2048 \ -pkeyopt rsa_keygen_pubexp:3 \ -out private/rsa_2048.key
-
ECDSA/P-256
openssl genpkey -algorithm EC \ -pkeyopt ec_paramgen_curve:P-256 \ -pkeyopt ec_param_enc:named_curve \ -out private/ecdsa_p256.key
-
EdDSA/25519 (supported by newer version of
openssl
and in TLS 1.3 only)openssl genpkey -algorithm Ed25519 \ -out private/ed25519.key
-
-
Create certificate signing request - intermediary step
-
RSA
openssl req -config openssl.cnf -new \ -sha256 \ -passin pass:test123 \ -key private/rsa_2048.key \ -out csr/rsa_2048.csr \ -days 9999
-
ECDSA
openssl req -config openssl.cnf -new \ -sha256 \ -passin pass:test123 \ -key private/ecdsa_p256.key \ -out csr/ecdsa_p256.csr \ -days 9999
-
EdDSA
openssl req -config openssl.cnf -new \ -passin pass:test123 \ -key private/ed25519.key \ -out csr/ed25519.csr \ -days 9999
-
-
Create server cert
Finally we can create set of server certificates.
-
RSA
openssl x509 \ -extfile openssl.cnf \ -extensions server_cert -sha256 -req \ -CA certs/ca.cert -CAkey private/ca.key -CAcreateserial \ -passin pass:test123 \ -in csr/rsa_2048.csr \ -out certs/rsa_2048.cert \ -days 9999
-
ECDSA
openssl x509 \ -extfile openssl.cnf \ -extensions server_cert -sha256 -req \ -CA certs/ca.cert -CAkey private/ca.key -CAcreateserial \ -passin pass:test123 \ -in csr/ecdsa_p256.csr \ -out certs/ecdsa_256.cert \ -days 9999
-
EdDSA
openssl x509 \ -extfile openssl.cnf \ -extensions server_cert -req \ -passin pass:test123 \ -CA certs/ca.cert -CAkey private/ca.key -CAcreateserial \ -passin pass:test123 \ -in csr/ed25519.csr \ -out certs/ed25519.cert \ -days 9999
-
It is currently believed that all private keys created above provide similar attack resistance, which is comparable to 128-bit symmetric cipher. Nevertheless, it’s worth to notice that byte size of those keys are much different.
Client cert creation
Commands below will create client private key and certificate that can be used for mutual TLS (client authentication). Procedure is similar to creating server certificate, so I’ll do it only for ECDSA.
- Client’s private key
openssl genpkey -algorithm EC \
-pkeyopt ec_paramgen_curve:P-256 \
-pkeyopt ec_param_enc:named_curve \
-out private/cli_ecdsa_p256.key
- Create certificate signing request - intermediary step
openssl req -config openssl.cnf -new \
-sha256 \
-passin pass:test123 \
-key private/cli_ecdsa_p256.key \
-out csr/cli_ecdsa_p256.csr \
-subj "/O=Cert Testing ORG/CN=Client Cert"
- Create client cert
openssl x509 \
-extfile openssl.cnf \
-extensions client_cert \
-req \
-CA certs/ca.cert \
-CAkey private/ca.key \
-CAcreateserial \
-in csr/cli_ecdsa_p256.csr \
-passin pass:test123 \
-out certs/cli_ecdsa_p256.cert \
-days 9999
Verification
In order to verify server certificate against CA following command can be used.
That’s it, I hope it helps, but most of all I hope I won’t have to look for this stuff ever again.
Also
Thank you to @mattcaswell from OpenSSL team, for helping to figure out how to create EdDSA certs.