Grabbing a copy of a server's TLS certificate
Sometimes you want to grab a copy of a server's TLS certificate - usually in order to perform Certificate Pinning. This is an additional security step used to provide additional assurance that the server you're talking to is the correct server (and is not, for example, an imposter using a bogus but legitimately issued certificate).
There are a number of different methods to do so, both from browsers and from the command line. This post documents a couple command line methods; a followup post will go into browser methods.
It should be noted - while we're on the topic - that Certificate Pinning is a controversial step to take, because it breaks things. In the ordinary course of events, when a certificate is replaced with a newer certificate, this change is invisible to the client, because both the old and the new certificate "check out" (in that they're issued by a valid CA, they're within valid dates, they're not on a CRL, etc. etc.). When you start pinning, you lose the ability to adapt when a certificate is replaced in the normal cause of business (expiration, compromise, addition of SAN names to the cert, etc. etc.). So if you're depending on access to a service, but trying to improve security by pinning, be aware that you may be shooting your availability/uptime in the foot, because when the certificate gets replaced by the server's owner your pinning will break the connectivity.
There are a number of different methods to do so, both from browsers and from the command line. This post documents a couple command line methods; a followup post will go into browser methods.
It should be noted - while we're on the topic - that Certificate Pinning is a controversial step to take, because it breaks things. In the ordinary course of events, when a certificate is replaced with a newer certificate, this change is invisible to the client, because both the old and the new certificate "check out" (in that they're issued by a valid CA, they're within valid dates, they're not on a CRL, etc. etc.). When you start pinning, you lose the ability to adapt when a certificate is replaced in the normal cause of business (expiration, compromise, addition of SAN names to the cert, etc. etc.). So if you're depending on access to a service, but trying to improve security by pinning, be aware that you may be shooting your availability/uptime in the foot, because when the certificate gets replaced by the server's owner your pinning will break the connectivity.
openssl
The openssl command line client can be used to connect to a TLS-enabled service, and prints out the server's certificate as part of the normal output (full example is here):
$ echo '' | openssl s_client -connect www.swynwyr.com:443
CONNECTED(00000003)
depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate
Signing, CN = StartCom Certification Authority
verify return:1
depth=1 C = IL, O = StartCom Ltd., OU = StartCom Certification
Authority, CN = StartCom Class 1 DV Server CA
verify return:1
depth=0 CN = www.swynwyr.com
verify return:1
---
Certificate chain
0 s:/CN=www.swynwyr.com
i:/C=IL/O=StartCom Ltd./OU=StartCom Certification
Authority/CN=StartCom Class 1 DV Server CA
1 s:/C=IL/O=StartCom Ltd./OU=StartCom Certification
Authority/CN=StartCom Class 1 DV Server CA
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate
Signing/CN=StartCom Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIF7zCCBNegAwIBAgIQGAvqmJHQF769z7eawoarHTANBgkqhkiG9w0BAQsFADB4
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEpMCcGA1UECxMg
U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJjAkBgNVBAMTHVN0YXJ0
...
5EkC0EHGoL7q37yraOOWXTizcqZEAj+LqLoySYKbe8EjsJ2AzuAErkptftiH4dgL
2xMeFZ7k2r7UsCkooQGF/cwblNTTTLSxd8bxXDthmBUDfZ8=
-----END CERTIFICATE-----
subject=/CN=www.swynwyr.com
issuer=/C=IL/O=StartCom Ltd./OU=StartCom Certification
Authority/CN=StartCom Class 1 DV Server CA
...
Now, I've shortened that output (marked by ...) but as you can see the server's certificate is their, in standard PEM x.509 format. You can grab that using an editor, or copy and paste, or you can just use sed to strip it out:
$ echo '' | openssl s_client -connect www.swynwyr.com:443 | sed -n '/BEGIN CERT/,/END CERT/p' > swynwyr.crt
And you can verify the contents of that PEM file using openssl again:
$ openssl x509 -text -noout -in swynwyr.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
18:0b:ea:98:91:d0:17:be:bd:cf:b7:9a:c2:86:ab:1d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=IL, O=StartCom Ltd., OU=StartCom Certification Authority, CN=StartCom Class 1 DV Server CA
Validity
Not Before: May 13 13:11:40 2016 GMT
Not After : May 13 13:11:40 2017 GMT
Subject: CN=www.swynwyr.com
Subject Public Key Info:
...
gnutls-cli
The gnutls-cli command can also be used to grab the cert (it is less commonly found than openssl, however).
$ echo '' | gnutls-cli --print-cert www.swynwyr.com
Processed 173 CA certificate(s).
Resolving 'www.swynwyr.com'...
Connecting to '65.19.178.92:443'...
- Certificate type: X.509
- Got a certificate list of 2 certificates.
- Certificate[0] info:
- subject `CN=www.swynwyr.com', issuer `C=IL,O=StartCom Ltd.,OU=StartCom Certification Authority,CN=StartCom Class 1 DV Server CA', RSA key 2048 bits, signed using RSA-SHA256, activated `2016-05-13 13:11:40 UTC', expires `2017-05-13 13:11:40 UTC', SHA-1 fingerprint `0a8eb691fca178dc0434d72ca7923d32de073cb4'
Public Key ID:
0ff5395413c86c6d93f0b053d02fece99cc3b3a8
Public key's random art:
+--[ RSA 2048]----+
| o+*=o |
| =**. |
| ..+o.o |
| . o oo .|
| S +. o |
| o .o |
| . + . |
| .B |
| E.. .+ |
+-----------------+
-----BEGIN CERTIFICATE-----
MIIF7zCCBNegAwIBAgIQGAvqmJHQF769z7eawoarHTANBgkqhkiG9w0BAQsFADB4
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEpMCcGA1UECxMg
...
5EkC0EHGoL7q37yraOOWXTizcqZEAj+LqLoySYKbe8EjsJ2AzuAErkptftiH4dgL
2xMeFZ7k2r7UsCkooQGF/cwblNTTTLSxd8bxXDthmBUDfZ8=
-----END CERTIFICATE-----
- Certificate[1] info:
...
Unlike openssl, gnutls-cli will default to printing all certificates (the server certificate and any intermediate certificates the server provides) so a slightly different sed line is used to grab the server certificate (which comes first); if pulling out the certificate with an editor, just grab the first certificate ("Certificate[0]"):
$ echo '' | gnutls-cli --print-cert www.swynwyr.com | sed -n '/BEGIN CERT/,/END CERT/p;/END CERT/q'
-----BEGIN CERTIFICATE-----
MIIF7zCCBNegAwIBAgIQGAvqmJHQF769z7eawoarHTANBgkqhkiG9w0BAQsFADB4
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEpMCcGA1UECxMg
...
5EkC0EHGoL7q37yraOOWXTizcqZEAj+LqLoySYKbe8EjsJ2AzuAErkptftiH4dgL
2xMeFZ7k2r7UsCkooQGF/cwblNTTTLSxd8bxXDthmBUDfZ8=
-----END CERTIFICATE-----
$
Comments
Display comments as Linear | Threaded