Using Certitude¶
Certitude has one job: validating the TLS certificates a server has sent you. To do that, you need to pass Certitude the TLS certificate chain sent by the server, and the hostname you’re expecting to connect to.
Getting A Certificate Chain¶
Certitude expects the TLS certificate chain as a list of TLS certificates
stored in the DER representation. Unfortunately, the Python standard library’s
ssl
module is not capable of providing the entire certificate chain, only
the leaf certificate. This means that to use Certitude you will need to use
pyopenssl or something like it: it’s just the only way to guarantee that
you get the complete certificate chain.
To get a certificate chain from PyOpenSSL, you’ll want to make the connection
as normal and then call get_peer_cert_chain()
. This will get you your cert
chain as a list of X509
objects. These will need decoding.
Given an already existing connection cnx
, you can get your list of
certificates like this:
certs = cnx.get_peer_cert_chain()
encoded_certs = [
OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, cert)
for cert in certs
]
Validating The Chain¶
Once you have the chain in place, it’s simple enough to validate it. Simply
pass the chain into certitude.validate_cert_chain
along with a unicode
string containing the expected hostname. For example:
valid = validate_cert_chain(encoded_certs, u'http2bin.org')
The validate_cert_chain
function returns True
if the cert chain is
valid, and False
in any other case.
Notes¶
When validating certificates using certitude you’ll likely want to disable
OpenSSL’s certificate validation. This is because OpenSSL and the
platform-specific TLS validation code will build their certificate chains
differently. In particular, OpenSSL may be unable to validate a chain that
the system library believes is valid. For that reason, put OpenSSL into the
VERIFY_NONE
mode and then handle the validation manually, after the
connection is made but before you send any data on it.
We cannot stress this enough: you must validate the certificates before sending or receiving data on the connection.