SSL Certificates
Subject Alternate Name
Usage
Subject Alternate Name (SAN) certificates allow you to mix several different domains in one certificate.
You might wonder where this would come in useful. In the bad old days, you used to require a distinct (IPv4) IP address for each SSL server you hosted. This was largely because early implementations of the SSL protocol didn't allow the client to specify which remote host it was trying to connect to. All they could do was wrapper traffic to/from an IP address with SSL. To be fair, SAN certificates have been "standardised" since 1999. Implementations came later.
Times have moved on and you can now (barring IE on XP and Android 2.x) make a server name indication (SNI) as you establish the SSL connection allowing the server to return the most appropriate certificate. How do SAN certificates help? Well, there's still only one piece of software running and the chances are it has a limit of one (or no limit) as to the number of SSL certificates it can hold in its hand at once. Stick a (largish) number of names on one certificate and you can now pretend to be a (largish) number of SSL websites.
How many is a largish number? That's not especially clear. 25? 100?
There are other situations, notably any protocol using STARTTLS, where you might address the server by a number of different names yet the server can only return a single certificate. Postfix is one example. Another MTA might not especially care about the CN or subjectAltName but a user who wants to SASL authenticate themselves to the MTA will have connected to smtp.example.com or smtp.example.net. It is vitally important to them that the certificate they see is valid for the name they connected to the server as.
CSR
We need to specify some "v3 extensions" which we can do in an extra section in the config file:
[ req ] ... v3_extensions = v3_req [ v3_req ] subjectAltName = ???
So, uh, what do we put? Well, the manual page, x509v3_config , tells you much and maybe everything. Rather than worry about email addresses, URI s etc. we might well stick with just DNS names.
The man page suggests we can write:
subjectAltName = DNS:foo.example.com, DNS:bar.example.net
which is fine but will begin to become a bit unreadable with a few more names. This is the short form we are looking at and we can choose to use the long form which is denoted by the syntax @section_name:
subjectAltName = @alt_names [ alt_names ] DNS.1 = foo.example.com DNS.2 = bar.example.net
which is much more readable.
Note
You don't need the .1 .2 etc. but the configuration file parser can't distinguish between the entries if you don't. Last one's the winner!
You can mix other types of subjectAltName into the certificate which might make sense for a webserver or MTA to include its IP address(es):
[ alt_names ] DNS.1 = foo.example.com DNS.2 = bar.example.net IP.1 = a.b.c.d IP.2 = w.x.y.z
Creating the CSR is no different than before:
openssl req -new -sha256 -key ssl-server-san.key -out ssl-server-san.req -config ssl-server-san-req.cnf
Check the SAN part:
openssl req -in ssl-server-san.req -noout -text Certificate Request: Data: Version: 0 (0x0) Subject: C=GB, ST=Buckinghamshire, L=Newport Pagnell, O=Example Limited, CN=Example Limited SSL Server/emailAddress=webmaster@example.com Subject Public Key Info: ... Attributes: Requested Extensions: X509v3 Subject Alternative Name: DNS:foo.example.com, DNS:bar.example.net Signature Algorithm: sha256WithRSAEncryption ...
Signing A SAN Cert Request
Unless we say otherwise the act of signing a SAN Cert Request will strip all the v3 extensions we've just applied. Boo! What do we need to say otherwise? Erm, all of the above, again. Is there any way to automate any of this? Not really. In a closed ecosystem you might want to be particularly lazy and generate the signing configuration file at the same time as the request configuration file (you are generating them automatically, aren't you?). You might simply grep for the DNS names in the request and re-apply them.
In a more public ecosystem you might want to pay more attention to what the odious wretches, er, by which I mean the paying customer is asking you to do.
Either way, you'll end up with a snippet of config file for signing this specific request which re-iterates the subjectAltName entries (notice we're dropping any IP alternate names):
[ v3_sign ] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always #basicConstraints = critical,CA:true basicConstraints = CA:true keyUsage = keyCertSign subjectAltName = @alt_names [ alt_names ] DNS.1 = foo.example.com DNS.2 = bar.example.net
and a signing command which references this snippet with -extfile and -extensions flags:
openssl x509 -req -sha256 -in ssl-server-san.req -out ssl-server-san.crt -extfile ssl-server-san-sign.cnf -extensions v3_sign -CA ssl-server-ca.crt -CAkey ssl-server-ca.key -CAserial ssl-server-ca.srl
Again, your subjectAltName entries should appear in the final cert:
openssl x509 -in ssl-server-san.crt -noout -text Certificate: Data: Version: 3 (0x2) Serial Number: 9 (0x9) Signature Algorithm: sha256WithRSAEncryption Issuer: C=GB, ST=Buckinghamshire, L=Newport Pagnell, O=Example Limited, CN=Example Limited SSL CA/emailAddress=webmaster@example.com Validity Not Before: Apr 9 20:44:44 2013 GMT Not After : May 9 20:44:44 2013 GMT Subject: C=GB, ST=Buckinghamshire, L=Newport Pagnell, O=Example Limited, CN=Example Limited SSL Server/emailAddress=webmaster@example.com Subject Public Key Info: ... X509v3 extensions: X509v3 Subject Key Identifier: B9:2B:29:0A:D6:E5:A6:0D:FA:B0:53:B3:6C:33:B5:96:E8:C7:59:E6 X509v3 Authority Key Identifier: keyid:42:CA:CF:B2:1C:EB:1F:37:7B:B0:D5:1A:3D:4B:9E:B8:D6:51:6F:17 DirName:/C=GB/ST=Buckinghamshire/L=Newport Pagnell/O=Example Limited/CN=Example Limited CA/emailAddress=webmaster@example.com serial:01 X509v3 Basic Constraints: CA:TRUE X509v3 Key Usage: Certificate Sign X509v3 Subject Alternative Name: DNS:foo.example.com, DNS:bar.example.net Signature Algorithm: sha256WithRSAEncryption ...
December 2017 Update
A reader writes:
"As I have been finding out, not only are they a convenience for multiple identities, SANs are now being enforced as a requirement since apparently the use of DNS names in the CN was deprecated in 2000 - who knew?"
—A reader
Not me, for sure! Pfft, don't they advertise these things?
Here, for reference is Chrome's deprecation of commonName as well as May 2000's RFC 2818 deprecation.
A bit more detail on what can be in SANs is hiding in RFC 5280 section 4.2.1.6:
SubjectAltName ::= GeneralNames GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName GeneralName ::= CHOICE { otherName [0] OtherName, rfc822Name [1] IA5String, dNSName [2] IA5String, x400Address [3] ORAddress, directoryName [4] Name, ediPartyName [5] EDIPartyName, uniformResourceIdentifier [6] IA5String, iPAddress [7] OCTET STRING, registeredID [8] OBJECT IDENTIFIER }
We've seen usage of DNS and IP which presumably are the dNSName and iPAddress above (there's something about the use of case there which is upsetting). How are the others used in an OpenSSL config file?
Well a quick Intertube and we have a Serverfault answer which (RTFS and) says you want to use:
- URI
- DNS
- RID
- IP
- dirName
- otherName
Note
There's no reference to x400Address or ediPartyName in that answer -- and I haven't looked in the code!
Document Actions