This blog post applies when the following two cases are true:
Your browser does not complain about your https site. Everything seems fine.
Some other tool does complain about not finding your certificate or not finding intermediate certificates. What is the problem?
So: your browser doesn’t complain. Let’s see a screenshot:
Some examples of complaining tools. First curl
:
$ curl https://api.letsgxxxxxxx
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
curl
has the right error message: Invalid certificate chain.
Let us look at wget
:
$ wget https://api.letsgxxxxxx
--2015-11-23 10:54:28-- https://api.letsgxxxxx
Resolving api.letsgxxxxxx... 87.233.157.170
Connecting to api.letsgxxxxxx|87.233.157.170|:443... connected.
ERROR: cannot verify api.letsgxxxxxx's certificate, issued by 'CN=COMODO RSA
Domain Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB':
Self-signed certificate encountered.
To connect to api.letsgxxxxxx insecurely, use `--no-check-certificate'.
wget
is right that it cannot verify …. certificate. But its
conclusion Self-signed certificate encountered is less helpful. The
certificate is not self-signed, it is just that wget
has to treat it that
way because the certificate chain is incorrect.
If you talk to such an https URL with java, you can see an error like this:
javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
This looks quite cryptic, but the cause is the same. SunCertPathBuilderException: CertPath sure sounds like a path to a certificate that it cannot find.
A final example is with the python requests
library:
>>> import requests
>>> requests.get('https://api.letsgxxxxxx')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/requests/api.py", line 69, in get
return request('get', url, params=params, **kwargs)
File ".../requests/api.py", line 50, in request
response = session.request(method=method, url=url, **kwargs)
File ".../requests/sessions.py", line 465, in request
resp = self.send(prep, **send_kwargs)
File ".../requests/sessions.py", line 573, in send
r = adapter.send(request, **kwargs)
File ".../requests/adapters.py", line 431, in send
raise SSLError(e, request=request)
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
So… you yourself discover the problem. Or a customer calls that he’s getting an error like this. Even though everything seems right if you test the https site in the browser.
Solution: go to https://www.digicert.com/help/
If that site says everything is completely right, then you’re done. If it still complains about something, you’ve got work to do.
Most of the checkmarks are probably green:
In cases like this, the problem is in the certificate chain at the bottom of the page. Here’s an example of one of our own sites from a few months ago:
Note the “broken chain” icon halfway. Just follow the chain from top to
bottom. Everything has to be perfect. We start with the *.lizard.net
which is issued by GeoTrust SSL CA - G2
.
The certificate GeoTrust SSL CA - G2
in turn is issued by GeoTrust
Global CA
.
The problem: the next certificate in the chain is not about GeoTrust
Global CA
, but about GeoTrust SSL CA
, which is different. Here the chain
breaks. It does not matter that the fourth certificate is about the GeoTrust
Global CA
we were looking for. The chain is broken. The order in which
the certificates are placed must be perfect.
After fixing the order of the certificates in our certificate file, the problem was fixed:
There are lots of certificates in the wild. All the browsers (and java, and your OS and…) often only store a handful (well, 20+) “root certificates”. All the other certificates have to trace their origin back to one of those root certificates.
That is where the intermediate certificates come in: they’re a cryptographically signed way to trace the validity of your certificate back to one of the known-good root certificates.
If you’re handling certificates yourself, you ought to know which files to edit. The main problem will be getting the right intermediary certificates from the issuing party. Often you only get “your” certificate, not the intermediary ones. Ask about it or google for it.
Often you won’t maintain those certificates yourself. So you have to get your hosting service to fix it.
If you let someone else take care of the certificate, point them at https://www.digicert.com/help/ and tell them to make sure that page is completely happy.
In my experience (=three times in the last two years!) they’ll mail back with “everything works now”. But it still won’t work. Then you’ll have to mail them again and tell them to really check https://www.digicert.com/help/ and probably provide screenshots.
Good luck!
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):