News

Welcome to End Point’s blog

Ongoing observations by End Point people

OpenSSL CSR with Alternative Names one-line

I find it hard to remember a period in my whole life in which I issued, reissued, renewed and revoked so many certificates.

And while that's usually fun and interesting, there's one thing I often needed and never figured out, till a few days ago, which is how to generate CSRs (Certificate Signing Requests) with AlternativeNames (eg: including www and non-www domain in the same cert) with a one-liner command.

This need is due to the fact that some certificate providers (like GeoTrust) don't cover the parent domain when requesting a new certificate (eg: CSR for www.endpoint.com won't cover endpoint.com), unless you specifically request so.

Luckily that's not the case with other Certificate products (like RapidSSL) which already offer this feature built-in.

This scenario is starting to be problematic more often since we're seeing a growing number of customers supporting sites with HTTPs connections covering both www and "non-www" subdomains for their site.

Luckily the solution is pretty simple and straight-forward and the only requirement is that you should type the CSR subject on the command line directly, basically without the use of the interactive question mechanism.

If you managed to understand how an SSL certificate works this shouldn't be a huge problem, anyway just as a recap here's the list of the meaning for the common Subject entries you'll need:

  • C => Country
  • ST => State
  • L => City
  • O => Organization
  • OU => Organization Unit
  • CN => Common Name (eg: the main domain the certificate should cover)
  • emailAddress => main administrative point of contact for the certificate

So by using the common syntax for OpenSSL subject written via command line you need to specify all of the above (the OU is optional) and add another section called subjectAltName=.

By adding DNS.n (where n is a sequential number) entries under the "subjectAltName" field you'll be able to add as many additional "alternate names" as you want, even not related to the main domain.

Obviously the first-level parent domain will be covered by most SSL products, unless specified differently.

So here's an example to generate a certificate which will cover www.endpoint.com and endpoint.com:

openssl req -new -key endpoint.com.key -sha256 -nodes
  -subj '/C=US/ST=New York/L=New York/O=End Point/OU=Hosting Team/CN=www.endpoint.com/
         emailAddress=administrative-not-existent-address@our-awesome-domain.com/
         subjectAltName=DNS.1=endpoint.com' > www.endpoint.com.csr

So here's another example with multiple DNS.n entries:

openssl req -new -key endpoint.com.key -sha256 -nodes
  -subj '/C=US/ST=New York/L=New York/O=End Point/OU=Hosting Team/CN=www.endpoint.com/
         emailAddress=administrative-not-existent-address@our-awesome-domain.com/
         subjectAltName=DNS.1=endpoint.com,
         DNS.2=usually-not-convered-domain.endpoint.com,
         DNS.3=multiple-domains-crt.endpoint.com' > www.endpoint.com.csr

warning: we had to split the command into multiple lines to make it readable, but you should keep it all on one line, otherwise you may lose some Subject details.

Now with that I'm able to generate proper multi-domain CSRs effectively.

Please note the use of the -sha256 to use the SHA256 algorithm to sign the CSR that, while not required, is appreciated considered the last round of concerning "attentions" to SHA1.

As one of our readers correctly pointed out, the certificate generate with this method won't comply with the X509v3 extensions.

Most of the time this is not a problem as we found that many big certificate authorities will be happy with the generated certificate and sign it for the right domains (NameCheap, GoDaddy, GeoTrust) though, just for completeness, be aware that if you need X509v3 compliance you should follow the usual standard configuration-file-based method.

16 comments:

Jon Jensen said...

Thanks, Lele. Great to have a single command for that.

One thing I'm curious about: I believe the RFCs state that if you use a Subject Alternative Name, you should supply all names as SANs, and the CN can be ignored by clients. If I understand correctly, that means you should list e.g. www.endpoint.com as the CN, and both www.endpoint.com and bare endpoint.com as SANs.

Can you confirm or deny that?

Emanuele 'Lele' Calo' said...

After some investigation I finally found a proper answer.

As can be read here, it seems that "some browsers" (yes, IE) may refer to this RFC strictly enough that if they found a SAN field they won't consider the CN field and only use the domains found in the SANs.

While the original "older" RFC didn't specifically endorsed nor encouraged that behavior, with the new RFC there was more confusion on how to read that part so some browser went that way.

The final answer is: since it's never a problem to have one domain in both fields (CN *and* SAN) but it can be a problem to have the main domain only in the CN when using SANs, it's better to have all domains present in both fields.

Since the CN only supports one domain, it's common practice to put the main domain there, and then repeat it in the SAN field along with all the additional ones.

Deikensentsu said...

This does not correctly generate the x509 certificate with the v3 extensions required for proper compliance with the RFC spec.

This can be verified by generating a certificate and then doing an 'openssl req -in yourfile.csr -noout -text' and looking for the v3 information.

I'm still interested in finding a one-liner, but so far I've had to build a openssl.cnf according to this other blog post and passed it in. http://apetec.com/support/GenerateSAN-CSR.htm

Emanuele 'Lele' Calo' said...

@Deikensentsu That's true.

Anyway I found that most certificate authorities are happy with the CSR generate that way and will create a certificate securing the right domains (NameCheap, GoDaddy, GeoTrust, ecc..)

Anyway thanks for your input, I'll add a line in the post text.

Have a great day.

sushil rangari said...

Hi ,

your command is not working for me, it giving me error like below

1)
Error opening Private Key endpoint.com.key
5133:error:02001002:system library:fopen:No such file or directory:bss_file.c:352:fopen('endpoint.com.key','r')
5133:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:354:
unable to load Private Key

2) when I remove endpoint.com.key from the command ,the csr which gets genrated do not have SAN in it, this is what I got in CSR

-----BEGIN CERTIFICATE REQUEST-----
MIIB8zCCAVwCAQAwgbIxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazER
MA8GA1UEBxMITmV3IFlvcmsxEjAQBgNVBAoTCUVuZCBQb2ludDEVMBMGA1UECxMM
SG9zdGluZyBUZWFtMRkwFwYDVQQDExB3d3cuZW5kcG9pbnQuY29tMRowGAYJKoZI
hvcNAQkBFgthQGdtYWlsLmNvbTEbMBkGA1UdERMSRE5TLjE9ZW5kcG9pbnQuY29t
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwp37aqOrAwCVWez7wh15oHK24
5LHMjh1WnNwOfdE/ZXurzD5Aipl3Xqdt70ECCujOHzYKELPSmpCvoGgNYU8BzWk/
Q94pqc7DZVzIqMPwmrwocGCntTvdiDclr4x2Gb7yR3X+SitTMFBE7NC1SLJkz6pz
pua0m27pf83D0QFxdQIDAQABoAAwDQYJKoZIhvcNAQELBQADgYEAdlYkMF+hIPEv
LyFCWFenaIPCpzfwiiCq7dgdefWUlh4agKTl1km0E1z/ZnkYhsTNGLE/E/MNrdkz
e2l/cvImEJEtb/mZlCBrHTgUaFjjX4yqhOcZbOkvSn8uJWkVvtcgcDUO+btfctp2
wBiDhc5rgzReWWo6IHPCTFIIE3KXbQg=
-----END CERTIFICATE REQUEST-----


on decoding above csr its giving me like below

Email: a@gmail.com/subjectAltName=DNS.1=endpoint.com

Please suggest

Emanuele 'Lele' Calo' said...

@sushil_rangari this post assumed readers to have a solid grasp of certificate creation/management basics. Before jumping on SANs you should probably practice more on basic certificates.
Specifically all the parameters should be customized to your specific situation.

sushil rangari said...

Hello Emanuele,

Thanks for replying back. Yes i do have some basic knowledge of Certificate Generations.

I replaced the contents of the your command as my need, but the desired CSR was not generated which i wanted. like specially for SAN

I have added www.domain.com as CN and under subjectAltName=DNS.1=domain.com

but the got SAN under email section

Email:name@gmail.com/subjectAltName=DNS.1=domain.com

am I doing some thing wrong ? do I need to made changes in openssl conf file as well ?

Please suggest .it will be helpful

Thanks
Sushil R

Emanuele 'Lele' Calo' said...

@sushil_rangari it seems that something could have been wrong in the command you used to generate the certificate. In order to be of any help I'd nee to see the steps you took to create the certificate. Please create a pastebin and I'll be happy to take a look and try to help.

sushil rangari said...

Hello Emanuele,

here is the commands which I am running

1) [root@master ~]# openssl req -new -sha256 -nodes -subj '/C=US/ST=New York/L=New York/O=IT/OU=Hosting Team/CN=www.domain.com/emailAddress=sushil.rangari84@gmail.com/subjectAltName=domain.com' > www.domain.com.csr
Generating a 1024 bit RSA private key
...............++++++
.........................++++++
writing new private key to 'privkey.pem'
-----

2) [root@master ~]# cat www.domain.com.csr
-----BEGIN CERTIFICATE REQUEST-----
MIIB8TCCAVoCAQAwgbAxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazER
MA8GA1UEBxMITmV3IFlvcmsxCzAJBgNVBAoTAklUMRUwEwYDVQQLEwxIb3N0aW5n
IFRlYW0xFzAVBgNVBAMTDnd3dy5kb21haW4uY29tMSkwJwYJKoZIhvcNAQkBFhpz
dXNoaWwucmFuZ2FyaTg0QGdtYWlsLmNvbTETMBEGA1UdERMKZG9tYWluLmNvbTCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1vHtUOHwPwajeEcXURRXzcs6aVre
vdKoG1M7FM8k2ryhtBaK0dLSbqyCb5huak7g9vnPG9IY8GIKyYHYUvN//QnPUomU
1zso2RJVKw0Bykkf4rRZSxkHDZsGLBNnw1Ut40utz92buNNSSWfq8l58kha9v+nH
UqGYB8KWVyns5zECAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4GBAHwqV3SHCVlwRovB
ra7b1SuRi1xXNXT5CT6FJWWVducisA9vxGTQ5pwSpvIexv3kAmv73ofWAyD1HOPM
BpSYv96Yw8PTnDh1Vz7vLMtvk1Ty4Bin4/oWx9p9kY1jj4/HGOmsmp0/yGRcbmhm
0zfR4jjctWE7t/jgwr5+EeJ0okS+
-----END CERTIFICATE REQUEST-----
[root@master ~]# openssl req -text -noout -verify -in www.domain.com.csr
verify OK
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, ST=New York, L=New York, O=IT, OU=Hosting Team, CN=www.domain.com/emailAddress=sushil.rangari84@gmail.com/subjectAltName=domain.com
Subject Public Key Info:


Please suggests.

Thanks
Sushil R

sushil rangari said...

In my previous command I missed DNS.1=

but after adding the result are same

[root@master ~]# openssl req -new -sha256 -nodes -subj '/C=US/ST=New York/L=New York/O=IT/OU=Hosting Team/CN=www.domain.com/emailAddress=sushil.rangari84@gmail.com/subjectAltName=DNS.1=domain.com' > www.domain.com.csr
Generating a 1024 bit RSA private key
....++++++
...........................++++++
writing new private key to 'privkey.pem'
-----


[root@master ~]# openssl req -text -noout -verify -in www.domain.com.csr
verify OK
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, ST=New York, L=New York, O=IT, OU=Hosting Team, CN=www.domain.com/emailAddress=sushil.rangari84@gmail.com/subjectAltName=DNS.1=domain.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption


Thanks
Sushil R

Emanuele 'Lele' Calo' said...

Hi Sushil Rangari,
That behavior you noticed is the same one the other reader noticed in saying that it's not "X509v3 compliant", specifically meaning that the SAN will be part of the subject field instead of having a dedicated field.
As I anticipated, this is not an issue with most certificate provider out there (NameCheap, GeoTrust, GoDaddy) while it may be an issue if you're dealing with software or appliances which needs certificates to be strictly X509v3 compliant.
In that case I suggest using the classical file-based SAN generation approach.

Thank you.

Michael Roedelbronn said...

Hi, I was wondering how one could use this format and also use a challenge phrase. When I use the syntax given it does not prompt for any further information. Putting /challengePassword=.../ doesn't seem to work.

Andrew Leahy said...

Hi Lele,

FYI your one liner didn't seem to add the subjectAltName to my CSR when I ran it thru a CSR decoder. But this one-liner did:

openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CA/O=Acme, Inc./CN=example.com" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr

Cheers, Andrew | Western Sydney Uni

Lyas Spiehler said...

I just developed a web based tool that will generate this command for you and display the output. http://kernelmanic.com/certificate-request-generator-with-multiple-common-names-and-subject-alternative-names/

Lyas Spiehler said...

I've updated my web based OpenSSL tool to automatically generate this command. https://certificatetools.com/

Starbeamrainbowlabs - said...

Thanks - this post is really helpful. I would say though that using "New York" as an example in the openssl command itself is very confusing - I can't tell the difference between the different fields. Perhaps it should be changed to something else?