Skip to content

Instantly share code, notes, and snippets.

@drmalex07
Last active April 16, 2024 20:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save drmalex07/df21b0b9d6b8d8d7a539 to your computer and use it in GitHub Desktop.
Save drmalex07/df21b0b9d6b8d8d7a539 to your computer and use it in GitHub Desktop.
Provide a certificate with extended attributes (X509 v3 extensions). #x509 #openssl #certificate

README

Configure OpenSSL

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.

Request a certificate

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.

Sign a certificate (as a CA)

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 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment