openssl req with SAN (subjectAltName)

Updated at by

I will tiptoe through generating a certificate signing request (csr) with openssl which includes X509 extension Subject Alternative Names (SAN). SAN extension in short can be used to validate multiple hostnames with the same certificate (eg. www.example.com and mail.example.com) or even combine multiple wildcards (eg. *.testing.example.com and *.example.com).

Or skip everything below and use a script from https://github.com/ospii/san. Clone https://github.com/ospii/san.git or git@github.com:ospii/san.git .

Fire up a terminal and start by generating a 4096 bit RSA keyfile in case you don't have one (bash variable substitution).

domain=example.com
openssl genrsa -out "${domain}.key" 4096

Following two variables will be passed to the openssl command when generating the CSR.

  • subjectAltName with two DNS names and one IP address. More options at openssl.org/docs - Subject alternative name
  • dn (distinguished name) is the unique name of your certificate and it contains multiple fields like C = Country, ST = State and CN = CommonName which is also used to match the hostname.

Requirements for the dn fields vary per certificate authority(CA) and level of validation. Some CAs might only need CN (CommonName) and some might require additional fields like emailAddress.

subjectAltName="DNS:${domain},DNS:www.${domain},IP:127.50.50.50"
dn="C=FI \n ST=Uusimaa \n L=Helsinki \n O=Öspi \n OU=Ospi \n CN=${domain}"
openssl req -out "${domain}.csr" -new -key "${domain}.key" -config <(printf "[req] \n prompt=no \n utf8=yes \n distinguished_name=dn_details \n req_extensions=san_details \n [dn_details] \n ${dn} \n [san_details] \n subjectAltName=${subjectAltName}")  

Two gotcha relating to this "beauty". dn has \n for new lines and prompt=no lurking in the [req] block fills all DN stuff from dn_details section in the -config file. This also implies openssl wont't use any fields provided in -subj parameter. It would have been nice to separate the static organizational fields from the CN but, alas, you can't have it all. Finally check everything is ok.

openssl req -in "${domain}.csr" -noout -text

Subject is the distinguished name of your certificate and requested extensions should have the X509v3 Subject Alternative Name block. Also verify the Signature Algorithm is sha256WithRSAEncryption. With older versions of openssl you might see sha1WithRSAEncryption or even md5WithRSAEncryption usually accompanied by nagging from your CA if you're to submit it. However this doesn't mean the issued certificate will use the same signature algorithm as it's only the signature of your request (csr). Anyway add -sha256 to the openssl req if anything other than sha256 pops up.

Certificate Request:
Data:
    Version: 0 (0x0)
    Subject: C=FI, ST=Uusimaa, L=Helsinki, O=Ospi, OU=Ospi, CN=example.com
...
...
    Attributes:
    Requested Extensions:
        X509v3 Subject Alternative Name: 
            DNS:example.com, DNS:www.example.com, IP Address:127.50.50.50
Signature Algorithm: sha256WithRSAEncryption

That's it. Happy SANing!


Leave a comment