When you validate server certificates from HTTPS clients, please be sure to use the right set of root certs. Mozilla maintain a decent list of these [1], but it's not in the PEM format that most HTTPS client libraries expect, e.g. Python's ssl.wrap_socket(sock, ca_certs="certs.pem").<p>Mozilla's list also includes <i>distrusted</i> certificates, so you need to be careful to leave them out when generating the PEM-encoded format. In fact, I'd strongly recommend using Adam Langley's excellent extract-nss-root-certs tool [2] which takes care of the subtle details for you.<p>And, if you are willing to trust me, you can download my pre-generated PEM-encoded cacerts file from a month or so ago [3].<p>[1] <a href="https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1" rel="nofollow">https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw...</a><p>[2] <a href="https://github.com/agl/extract-nss-root-certs" rel="nofollow">https://github.com/agl/extract-nss-root-certs</a><p>[3] <a href="https://github.com/downloads/tav/ampify/distfile.cacerts-2012.06.28.tar.bz2" rel="nofollow">https://github.com/downloads/tav/ampify/distfile.cacerts-201...</a>
In this age of high-level languages, why do I still have to worry about this? I don't mean 'security' I mean 'managing certificates.' My local framework/API should complain if I don't have a trusted root and should then make it dead simple to provide that root.
Java uses a keystore (actually - being Java - you can set a property to tell it which keystore to use).<p>Importing a new certificate is documented here: <a href="http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Security10.html" rel="nofollow">http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Security10.htm...</a><p>The verification of the certificate is delegated to a TrustManager[1]. Certificate paths can be checked[2] and the TrustManager is flexible enough to support a large variety of verification scenarios[3].<p>[1] <a href="http://docs.oracle.com/javase/1.4.2/docs/api/javax/net/ssl/TrustManager.html" rel="nofollow">http://docs.oracle.com/javase/1.4.2/docs/api/javax/net/ssl/T...</a><p>[2] <a href="http://www.exampledepot.com/egs/java.security.cert/ValidCertPath.html" rel="nofollow">http://www.exampledepot.com/egs/java.security.cert/ValidCert...</a><p>[3] <a href="http://stackoverflow.com/questions/11681474/how-can-i-trust-a-specific-self-sign-certificates-not-trust-all?lq=1" rel="nofollow">http://stackoverflow.com/questions/11681474/how-can-i-trust-...</a>
If you want to check any 3rd party apps or frameworks that you use you can set up a proxy like Fiddler, configure it to do a MITM attack on you, and see if the client/API blows up with an error or just keeps on truckin'.
Getting this right was a big pain when we were implementing the various Stripe client libraries. We had to resort to hacks even in mainstream languages.
Python: Just check the certificates with Python Requests (or take one of 20 lines urllib solutions):<p>>>> requests.get('<a href="https://exmaple.com" rel="nofollow">https://exmaple.com</a>, verify=True)
requests.exceptions.SSLError: hostname 'exmaple.com' doesn't match either of '*.exmaple.org', 'exmaple.org'
So presumably, decent high-level languages (like Python) do use an encrypted connection - they just don't ensure the right person is on the other end of that connection?
To make it worse in many languages there not built in OCSP or CRL facilities to go with their standard TLS wrappers. e.g. The best you get in Python is checking against a CA list. So even if you do go to the trouble to turn on CA verification yourself you still accept known bad certificates.
Great Article! Looks like as of Curl 7.10 PHP now checks this by default:
CURLOPT_SSL_VERIFYPEER
CURLOPT_SSL_VERIFYHOST<p><a href="http://php.net/manual/en/function.curl-setopt.php" rel="nofollow">http://php.net/manual/en/function.curl-setopt.php</a>
The problem with doing this is that many/most enterprise IT shops use security devices to proxy SSL traffic, altering the cert that the client sees.<p>So unless you really understand you app's deployment scenario well, you should proceed with caution. Also note that 2% of enterprise IT people understand SSL at all, (and the devices that do the MITM part are usually controlled by the security dept) so troubleshooting will be close to impossible.
Java HTTPS server code allows the developer to configure the X.509 trust manager. My API uses Java for both client and server and transmits JSON messages over secure web sockets which is built over HTTPS. Works great. I authenticate on both client and server, and am just now developing an iOS Objective C client that runs wss.
Node.js seems to omit using a certificate as well. From the documentation:<p>* cert: Public x509 certificate to use. Default null.<p>[1] <a href="http://nodejs.org/docs/latest/api/https.html#https_https_request_options_callback" rel="nofollow">http://nodejs.org/docs/latest/api/https.html#https_https_req...</a>
i know in the the world of .NET (atleast on Windows) it'll automatically check using the cert manager. Anyone know how this might work on platforms such as Java? I'd assume the local VM would need to have some OS specific plumbing in place.
Validating certificates is a good thing and everybody should do it.<p>That said ... it really only tells you that a certificate is 'sound'. It by no means tells you with 100% confidence that you are talking to the right party.<p>SSL/TLS is still pretty fragile.
The twilio-ruby library does this by packaging a set of root ca certs. There is a configuration option to override this with your own set when you construct the client.
This is default behaviour in Ruby, and as mentioned in the article, one can set up a custom store.<p>With all the languages that support this by default, I'm surprised Python doesn't.