Your OpenSSL CSR command is out of date

January 29, 2020

Here's what 'openssl req' looks like in 2015

an image

By Mike on 13th April 2015

The OpenSSL docs are the official guide to OpenSSL options. But external, task-based documentation is often used instead, particularly for the task of making a Certificate Signing Request to get an SSL certificate.

Most guides to making a Certificate Signing Request are out of date. Specifically they:

  • Use old RSA key sizes that have been replaced in current OpenSSL and which are too weak for a green bar and company name (EV certificate).
  • Focus on the CN, which in many cases may never be used by current browsers.
  • Use signing algorithms that will produce warnings in current browsers.

While CertSimple builds the command to non-interactively generate the CSR for you, it's still important to know:

  • What the command we generate does
  • Why we set certain values

Here's a 2015-era openssl CSR request for an EV cert:

openssl req -newkey rsa:2048 -nodes -sha256 -keyout example.private-key -out example.csr -subj '/NOT=THE/ACTUAL=SUBJECT/YOU=WILL/GET=IN/YOUR=CERTIFICATE'

Let's break it down:

req - enter OpenSSL's 'request' command

OpenSSL has different modes, officially called 'commands' specified as the first argument. After you specify a particular 'command', all the remaining arguments are specific to that command. Eg:

  • the enc command is great for encrypting files.
  • the s_client command is an SSL client you can use for testing handshakes against your server.
  • the req command for requesting certificates - which is what we're using today.

-newkey rsa:2048 - 2048 bit encryption required for the green bar with a company name (EV)

-newkey rsa:2048 creates a new private key with 2048-bit RSA encryption. Your OS probably has an old version installed, but the current OpenSSL uses a 2048 bit key by default. If you want to get an EV cert to prove the identity of your company, and show that in the green bar in browsers browser makers and CAs require a 2048-bit key at minimum.

-sha256 - sign the CSR using an algorithm that won't trigger browser warnings

Use the SHA256 algorithm to sign the CSR. Most CAs will use the CSR signature to determine the signing algorithm for the certificate itself, and a SHA256 cerrtificate signature is is required in current generation browsers. The default is SHA1, which is considered out of date and will create warnings or be rejected entirely depending on when your certificate expires.

If you ordered a 2-year SHA1 certificate right now, here's what it would look like in the mid April 2015 version of Chrome:

Chrome 42 displaying an SHA1 certificate

A new 2 year certificate with an SHA1 signature in Chrome 42, mid April 2015

Update: not all CAs use the CSR signature to determine the signing algorithm for the certificate itself - thanks to Philip Hofstetter & Brian Sniffen on Hacker News for pointing this out.

-nodes - don't require a password to be entered before using the key

-nodes stands for 'no DES'. But the name is a little misleading. nodes stops OpenSSL from encrypting the private key file. Encrypting the private key sounds like a good idea, but it means that you web server will need some kind of manual intervention to restart and load the key (eg, someone typing the password).

Most CAs and hosting services recommend using the -nodes option to not encrypt the private key file. Unless you have a guaranteed secure way of providing the key to your server when it restarts, using a password on your key file can make things worse - either slowing down your web server start time when you need it back up, or prompting people to store the private key password in an insecure fashion so they restart the web server. Some services, like AWS's ELB, simply don't work with passwords on private keys. So we recommend nodes unless you have a secure, automated mechanism of providing the private key passphrase.

PS: if you omit -nodes the key wouldn't be encrypted with DES these days (since DES is considered insecure), but rather 3DES - you can also select other encryption options like AES or Camellia.

-keyout

-keyout somefile.key this is the private key. It's value is not easily guessed. Don't give it to anyone outside your company.

-subj the subject, but not necessarily the subject that your company will receive on your certificate

-subj contains the actual thing you want the CA to attest to by signing your certificate, so it's mandatory. Most SSL vendors make you fill in the subject interactively when openssl runs, supplying some documentation explaining to you how to convert the fields and hoping you don't make a mistake. But the full subject can be provided on the command line, the same as any other field. Here's a basic version for an old-style non-EV cert:

openssl req -nodes -sha256 -newkey rsa:2048 -keyout example.com.private-key -out example.com.csr -subj '/C=GB/L=London/O=Example Inc/CN=example.com'

Now here's a full OpenSSL command that generates all the info you would see on an EV certificate:

openssl req
-newkey rsa:2048 \
-nodes \
-sha256 \
-keyout example.private-key \
-out example.csr \
-subj '\
/O=Example Ltd\
/businessCategory=Private\
/serialNumber=5157550\
/jurisdictionOfIncorporationCountryName=Delaware\
/C=US\
/streetAddress=123 My Street\
/ST=California\
/CN=example.com\
/subjectAltName=DNS.1=example.com, DNS.2=www.example.com, DNS.3=billing.example.com'

Huge right? That's not all - you'll probably also have to make OpenSSL know about the new fields required for EV: by adding the following under [new_oids] in /System/Library/OpenSSL/openssl.cnf (OS X) or /etc/ssl/openssl.cnf (Linux):

[ new_oids ]

businessCategory=2.5.4.15
streetAddress=2.5.4.9
stateOrProvinceName=2.5.4.8
countryName=2.5.4.6
jurisdictionOfIncorporationLocalityName=1.3.6.1.4.1.311.60.2.1.1
jurisdictionOfIncorporationStateOrProvinceName=1.3.6.1.4.1.311.60.2.1.2
jurisdictionOfIncorporationCountryName=1.3.6.1.4.1.311.60.2.1.3

But there's a simpler way: CSRs can (and often are) changed by CAs before signing them. More on that later.

For now, let's go through the fields, because whether they are included on your CSR or not, they will be part of your order and they will be on your certificate.

If you've made certs before, you know some of the fields already, but there are two interesting new ones you'll see above, and if you inspect certificates in your browser:

EV certificate subject

You can see GitHub's company registration in Delaware from it's EV certificate.

The registered company serialNumber with the state (US) or national (most other countries) body.

  • If you look at GitHub's certificate in your browser, serialNumber is 5157550 and their jurisdictionOfIncorporationCountryName (shown as 'Inc. State or Province' in Chrome) is Delaware. If you look around at company registration online, you can indeed see that GitHub Inc was registered on 2012-07-02, in Delaware, with company ID 5157550.

  • If you look at the CertSimple certificate in your browser, jurisdictionOfIncorporationCountryName is UK and our serialNumber is 09378892 - which matches the Companies House record.

The subjectAltNames, ie. the domain names

subjectAltName are domain names for multi-server certificate certificate. You can easily see the subject alt names for any website by clicking the identity bar and checking out the certificate information. Here's GitHub's Subject Alt names:

Subject Alternate Names

subjectAltNames are the names of your servers. People often refer to these as 'domain names', but that's not quite correct: they're server hostnames, specified as a 'fully qualified domain name' which is Unix terminology for 'full hostname including the domain'. Put all your domain names into the Subject Alt Name field.

Before EV, the CN (Common Name) field was used for these. But since:

Every EV certificate these days has at least 2 SubjectAltNames. RFC6125 in 2011 - which is used by current browsers - says that browsers must check SAN first, and if SAN exists, the CN should not be checked. So, if you want multiple names for your certificate, put all names into the Subject Alt Name field - because if a domain name is is the CN but not the SANs list, it won't work - at least in current stable Chrome.

We mentioned how in practice nobody ever has to fill in a giant CSR to get an EV certificate: in practice, every SSL vendor has a form submitted alongside the CSR. When issuing an EV certificate, a CA will take the forms contents and:

  • modify the subject to include verified company number, and where it was verified. For the US, that's the state, for the UK, it's nationally.
  • Set the physical address that has been verified.
  • correctly include all the domain names as SubjectAlternateNames.

    CSRs are fixed by CAs to include the company, the physical address, and add all servers.

So, most CSRs, even in 2015 looks like the first example, allowing users to run a shorter command, sending extra details outside the CSR (via an API call or some additional UI) and having the verifying CA fix the subject to match what they're verifying.

-out

-out is the file name for the certificate signing request that will be made, containing the public key and the subject.

Conclusion

So there you have it. In short:

  • sha256 is required for Chrome 42+ (mid April 2015) not to show warnings.
  • 2048 bit RSA is the new OpenSSL default and is required for EV certificates.
  • The 'subject' (the thing being attested to by the CA) you actually get in your certificate will probably have a lot more detail than the subject line in your CSR, and that's a good thing.
  • If you're using EV, and have at least www and non-www, the CN will never be used - your CA will put all the domain names inside the SAN fields. Anything else won't work with current browsers.