Is it possible to create a CA certificate (even unsigned), which is only allowed to sign certificates for specific limited domain(s), so that it can't be misused for other domains?
- 18,093
- 1
- 52
- 86
- 1,781
- 4
- 17
- 26
-
Do you mean in an enterprise domain environment with multiple domains you have a CA in one domain? And you only want it to be valid in that domain? – NULLZ Feb 23 '13 at 11:26
-
3I mean allow the CA certificate to sign for limited amount of domains so it can't be misused for other domains. – Smit Johnth Feb 23 '13 at 13:24
-
1The current top answer, published by Thomas Pornin in 2013, seems to be out of date. See e.g. reports by David Tomaschik and Jedri Visser. – JamesTheAwesomeDude May 22 '23 at 17:02
2 Answers
Thomas Pornin's answer is good, but a little outdated. Support for Name Constraints is growing.
I've found that OpenSSL 1.0.1k and Windows 7 support the extension.
Test
Using XCA, I created a self-signed CA certificate, and added a critical Name Constraints extension for .lab.example.com, by adding the following line on the "Advanced" tab during certificate creation:
nameConstraints=critical,permitted;DNS:.lab.example.com
Note: the constraint should not have a leading dot. It's technically incorrect, but support for this is expanding: https://github.com/golang/go/commit/e4dafa32620e80e4e39937d8e2033fb2ee6085f8
Then, I used that CA certificate to sign two other certificates for HTTPS servers:
test.lab.example.com- Validbad.google.com- Clearly invalid
Next, after setting up DNS entries accordingly, I used this modified simple-https-server.py to run an HTTPS server, once with each of the generated certificates:
./simple-https-server --certfile test.lab.example.com.pem --hostname test.lab.example.com
and
./simple-https-server --certfile bad.google.com.pem --hostname bad.google.com
After installing the CA certificate into the OS trust, I then tried to visit each site with several clients.
Results
OpenSSL 1.0.1k seems to support this. curl gave me the following error when I tried to visit bad.google.com:
curl: (60) The Certifying Authority for this certificate is not permitted to issue a certificate with this name.
Chrome on Windows 7 also does the right thing. Chrome gives a fairly generic net::ERR_CERT_INVALID, but Windows certificate viewer is quite explicit:
The certificate has an invalid name. The name is not included in the permitted list or is explicitly excluded.
References
Update 1
I also tried signing a certificate that did not specify a Subject Alternative Name, instead relying on the old common-name only.
OpenSSL / curl still refused to accept the certificate.
Both Chrome and IE11 on Windows refused to accept the certificate on Windows, even though windows itself (when viewing the server certificate) didn't complain about it. To me, that means that the browsers are doing more than simply asking the OS to verify the certificate, which is a good thing.
Note that name constraints are not properly supported on OSX earlier than 10.13.3 which was released early 2018.
Conclusion
I feel secure in asking others to install my root CA certificate, without putting them at any risk.
- 163
- 1
- 4
- 862
- 7
- 13
-
1
-
@SmitJohnth Chrome and IE use the Windows SSL library; Firefox uses its own. I don't know about any others. – Jonathon Reinhart Jul 21 '16 at 23:11
-
I can't make this work for me, any advise? https://serverfault.com/questions/859551/limiting-power-of-a-trusted-certificate/ – user1156544 Jul 06 '17 at 09:25
-
I am not sure the leading dot is technically incorrect. It seems to be accepted in the RFC – user1156544 Feb 05 '18 at 16:38
-
2https://bugs.chromium.org/p/chromium/issues/detail?id=1072083 on Chrome on Linux, as of now, this doesn't work on root CA, only on intermediate CAs – WGH Jun 03 '20 at 08:04
-
-
What's the format for
nameConstraints=if I want to allow multiple domains? E.g. botha.example.comandb.example.combut notanything-else.example.com. – iBug Jul 19 '21 at 10:07 -
Does this also apply to intermediate CAs? Can we expect prices/compliance overhead for name-constrained intermediate CAs to drop in the future? – Benni Oct 05 '21 at 10:09
-
"Does this also apply to intermediate CAs?" Yes. I have deployed a PKI where the offline root is unconstrained (for future use), and the online intermediate issuing CA is constrained to the business domain. As I've only done this on private, internal PKIs, I cannot comment on your second question. – Jonathon Reinhart Oct 05 '21 at 13:12
No.
(I assume you are talking about certificates for SSL servers.)
Technically no. What would be closest to that would be the Name Constraints extension (see section 4.2.1.10 of RFC 5280) (OID 2.5.29.30), which theoretically allows for restricting a complete PKI subtree to an explicit set of domains (and subdomains thereof). The extension supports both whitelist and blacklist semantics (in your case, you would like a whitelist). In practice, however, this fails for two reasons:
The
Name Constraintsextension is mostly unsupported by existing implementations of SSL. They are likely to ignore the extension.When a SSL client connects to a server, it looks for the server name in the server certificate, as specified in RFC 2818, section 3.1. It will look for names of type
dNSNamein aSubject Alt Nameextension, and these names are covered (theoretically) by theName Constraints. However, if the server certificate lacks aSubject Alt Nameextension, clients will fall back on the Common Name (in thesubjectDN). The Common Name is not in scope of theName Constraints. This means that a certificate could evade the name constraints by omitting theSubject Alt Nameextension and putting an arbitrary server name in its Common Name.
(This is the whole story of X.509: lots of hooks and provisions for many useful features, which don't work because of lack of support from implementation and lack of coordination between specification bodies.)
- 326,555
- 60
- 792
- 962
-
The Common Name is not in scope of the Name Constraints< - well, what is it for then? About support: most browsers even doesn't support newest SSL versions.
– Smit Johnth Feb 23 '13 at 14:08 -
6Common Name is in scope of Name Constraints of type
distinguishedName, which do not apply the domain-specific semantics; X.509 was not designed for storing a server name in the Common Name, but the name of a human being. Using the Common Name as a server name is a hack which, alas, we must live with since it is widespread. – Thomas Pornin Feb 23 '13 at 14:11 -
-
Damn! I made it work with successfully testing and then I read your answer (Common Name) – Oct 18 '15 at 14:05
-
To make things worse, hexchat failed to validate it because of some openssl bug – Oct 18 '15 at 19:01
-
1Things are looking up, though. For example, I have an old internal certificate that I didn't use a
Subject Alt Namefor, and just stuck the domain name in the Common Name. Now, when I use Python Requests to hit an API on an HTTPS server with that certificate, I get the following error: SubjectAltNameWarning: Certificate for foo.example.com has nosubjectAltName, falling back to check for acommonNamefor now. This feature is being removed by major browsers and deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 for details.) – Jonathon Reinhart Jan 15 '16 at 17:14 -
10Nowadays (2018) many browsers (like Chrome) no longer treat certificates without a "Subject Alt Name" as secure. Does that mean that these Name constraints have become a viable option? – Niels Basjes Apr 22 '18 at 20:05
-