The creation of a certificate has a request phase and a signing phase. Both phases need to refer to an SSL configuration
file which will include the required extensions. The supported extensions are documented at man x509v3_config
.
The system-wide openssl configuration usually lies at /etc/ssl/openssl.cnf
. Suppose we need to request some X509 extensions (like keyUsage
, extendedKeyUsage
and subjectAltName
), so we need to add/override some parts and we create a configuration fragment in request.conf
:
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = GR
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Greece
localityName = Locality Name (eg, city)
localityName_default = Athens
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Nowhere Land
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = devel
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = foo.example.com
emailAddress = Email Address
emailAddress_max = 64
[ reqexts ]
keyUsage = nonRepudiation,digitalSignature,keyEncipherment
extendedKeyUsage = critical,serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = foo.example.com
DNS.2 = baz.example.com
The above configuration will be referenced at request phase.
Suppose we have a normal RSA key at key.pem
and we want to create a certificate signing request (CSR). Generate the request (provide the needed configuration on-the-fly):
openssl req -new -out req.pem -key key.pem \
-reqexts reqexts \
-config <(cat /etc/ssl/openssl.cnf request.conf)
Note that the value passed to -reqexts
option is the name of the section defining the X509 extensions.
The signer (CA) must also be configured to take extensions into account.
The easiest way is to add copy_extensions=copy
to the section of the CA configuration (see also https://gist.github.com/drmalex07/32b77653d95ff8df5728). But this option should be used with caution!
Another option is to explicitly specify which X509 extensions are recognized.
For key usage we can simply add sections in ca.conf
. For example:
[ca]
default_ca = default
[default]
...
x509_extensions = default_extensions
...
[default_policy]
...
[default_extensions]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical,serverAuth
If we need to support SANs (subject alternative names), which are request-specific names, we need to craft a temporary extension file which contains those. For example (the name _req_exts
is arbitrary, and is chosen just to differ from other section names present in main ca.conf
):
extension_file=$(mktemp -p /tmp --suffix .conf ca-ext-XXXXXX)
cat <<EOD >${extension_file}
[_req_exts]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical,serverAuth
subjectAltName=DNS:foo.example.com, DNS:baz.example.com
EOD
Now sign the cerificate using -extfile
to point to the request-specific configuration and -extensions
to point to the specific section:
openssl ca -config ca.conf -extfile ${extension_file} -extensions _req_exts \
-in foo.csr -out foo.crt