I think that we can surely say that, with all its deficiencies, SSL/TLS is still a protocol we cannot live without, and basis of todays secure communication on the Internet.Quite often I get asked on how certificates are really verified by browsers or other client utilities. Sure, the canned answer that certificates get signed by CAs and a browser verifies if signatures are correct is always there, but more persistent questions on how it exactly works happen here and there as well.
So, if you ever wondered on how a certificate could be fully manually verified by checking all the steps, this is a diary for you!">$ openssl s_client -connect isc.sans.edu:443 /dev/null | sed -ne /-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p ">$ openssl verify -verbose isc.sans.edu.pem
isc.sans.edu.pem: C = US, postalCode = 20814, ST = Maryland, L = Bethesda, street = Suite 205, street = 8120 Woodmont Ave, O = The SANS Institute, OU = Network Operations Center (NOC), OU = Unified Communications, CN = isc.sans.edu
error 20 at 0 depth lookup:unable to get local issuer certificate
Hmm, no luck. But that is because the CA file that comes with Linux by default is missing some of the intermediates. Those either have to be in the CA store, or the server has to deliver the whole chain to us when we initially connect. Ok, not a problem lets continue manually.
First we can see who the issuer really here is, and what are the certificate">$ openssl x509 -in isc.sans.edu.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
24:21:68:a7:55:13:74:1a:d1:95:fb:62:26:90:c9:1d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Organization Validation Secure Server CA
Validity
Not Before: Apr 7 00:00:00 2015 GMT
Not After : Apr 6 23:59:59 2018 GMT
">$ openssl x509 -in isc.sans.edu.pem -noout -subject -issuer -nameopt RFC2253
subject= CN=isc.sans.edu,OU=Unified Communications,OU=Network Operations Center (NOC),O=The SANS Institute,street=8120 Woodmont Ave,street=Suite 205,L=Bethesda,ST=Maryland,postalCode=20814,C=US
issuer= CN=COMODO RSA Organization Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
So, let it">$ curl https://curl.haxx.se/ca/cacert.pem -o cacert.pem
The file even contains name of CAs in plain text. Let">$ grep -i Comodo cacert.pem
Comodo AAA Services root
Comodo Secure Services root
Comodo Trusted Services root
COMODO Certification Authority
COMODO ECC Certification Authority
COMODO RSA Certification Authority
It doesnt have the one that we need: remember that it must match precisely to the CN field! This also confirms that it is an intermediate CA. We will probably have to find the intermediate CAs certificate on Comodos web site. Lets paste the name into Google (COMODO RSA Organization Validation Secure Server CA) and see what we get.
The first hit will lead us to https://support.comodo.com/index.php?/Default/Knowledgebase/Article/View/968/108/intermediate-ca-2-comodo-rsa-organization-validation-secure-server-ca-sha-2 and sure - this is were our intermediate CA is. Let">$ curl https://support.comodo.com/index.php?/Knowledgebase/Article/GetAttachment/968/821025 comodo.crt
Now let">$ openssl x509 -in comodo.crt -subject -issuer -noout -nameopt RFC2253
subject= CN=COMODO RSA Organization Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
issuer= CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
Great! Thats exactly what we need ">$ grep COMODO RSA Certification Authority cacert.pem
COMODO RSA Certification Authority
It is a root CA, that exists in Mozilla cacert.pem so we have the full chain!
Let">$ openssl x509 -in isc.sans.edu.pem -noout -text | grep Signature
Signature Algorithm: sha256WithRSAEncryption
Ok, SHA256 with RSA (great job Johannes on renewing the cert properly :)). What does this mean? This means that the critical parts of the certificate have been hashed by the CA with the SHA256 hashing algorithm and then encrypted with CAs private key. Its public key is available in the comodo.crt file we just downloaded (and isc.sans.edu">$ openssl x509 -in isc.sans.edu.pem -noout -text
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:d4:8f:58:63:f4:30:0b:ad:05:d0:37:f1:69:97:
6e:27:90:a5:dd:43:d7:c5:30:0d:dc:73:80:6a:fc:
What we need to do know is the following:
- We need to extract the signature from the certificate and then use Comodo with this we will get the SHA256 hash of the certificate
- Then we need to calculate our own SHA256 hash of the certificate
- If those two match: the certificate is signed properly
In order to extract components of a certificate we need to decode it to ASN.1 format. Luckily, openssl can do that for us, so lets see what we get on isc.sans.edu">$ openssl asn1parse -in isc.sans.edu.pem
1582:d=1 hl=2 l= 13 cons: SEQUENCE
1584:d=2 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
1595:d=2 hl=2 l= 0 prim: NULL
1597:d=1 hl=4 l= 257 prim: BIT STRING
So, the last object is actually the signature it starts at offset 1597, so let">$ openssl asn1parse -in isc.sans.edu.pem -out isc.sans.edu.sig -noout -strparse 1597
Now we got the file isc.sans.edu.sig, which is RSA encrypted SHA256 of the signature. How do we decrypt it? We need Comodos public key, which is available in its certificate, so let">$ openssl x509 -in comodo.crt -pubkey -noout comodo.pub
Now that we have the Comodos public key, we can finally decrypt the SHA256 hash. It will work only if the original has been encrypted with the corresponding private key. Well get an ASN.1 structure back so let">$ openssl rsautl -verify -pubin -inkey comodo.pub -in isc.sans.edu.sig -asn1parse
0:d=0 hl=2 l= 49 cons: SEQUENCE
2:d=1 hl=2 l= 13 cons: SEQUENCE
4:d=2 hl=2 l= 9 prim: OBJECT :sha256
15:d=2 hl=2 l= 0 prim: NULL
17:d=1 hl=2 l= 32 prim: OCTET STRING
0000 - 4b ca b8 23 4d 52 da e1-31 f1 0d b0 ba 3d 33 6b K..#MR..1....=3k
0010 - 0e 3d 68 0f 99 cb 35 43-69 ff 70 d0 1d a6 ef c1 ">$ openssl asn1parse -in isc.sans.edu.pem
0:d=0 hl=4 l=1854 cons: SEQUENCE
4:d=1 hl=4 l=1574 cons: SEQUENCE
8:d=2 hl=2 l= 3 cons: cont [ 0 ]
10:d=3 hl=2 l= 1 prim: INTEGER :02
13:d=2 hl=2 l= 16 prim: INTEGER :242168A75513741AD195FB622690C91D
31:d=2 hl=2 l= 13 cons: SEQUENCE
33:d=3 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
Ok, the first object starts at offset 4, let">$ openssl dgst -sha256 -hex tbsCertificate
SHA256(tbsCertificate)= 4bcab8234d52dae131f10db0ba3d336b0e3d680f99cb354369ff70d01da6efc1
Remember the decrypted ASN.1 object? Scroll up ">
17:d=1 hl=2 l= 32 prim: OCTET STRING
0000 - 4b ca b8 23 4d 52 da e1-31 f1 0d b0 ba 3d 33 6b K..#MR..1....=3k
0010 - 0e 3d 68 0f 99 cb 35 43-69 ff 70 d0 1d a6 ef c1 .=h...5Ci.p.....
Yay! Its a full, 100% match. So the certificate is correctly signed by Comodos intermediate. We could now repeat all the steps to verify if the intermediate CA is correctly signed by the root CA that we got from Mozilla">$ cat comodo.crt cacert.pem
$ openssl verify -verbose -CAfile cacert.pem isc.sans.edu.pem
isc.sans.edu.pem: OK
And that gets us to the end of verification.
-- Bojan
https://twitter.com/bojanz
INFIGO IS