How get certificate which is being used on SSL handshake?

Is there a way do send some HTTP method to a specific endpoint and get back the certificate which is being used by the endpoint?

Suppose I have the endpoint https://myendpoint.mydomain.com/mycontext/myservice

I would like to obtain the certificate information that this endpoint is serving to my attempt to consume it.

Upvotes: 0

Views: 820

Answers (1)

evilSnobu
evilSnobu

Reputation: 26424

Here's the canonical openssl s_client example:

$ openssl s_client -connect github.com:443 -servername github.com

CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com,
        CN = DigiCert High Assurance EV Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com,
        CN = DigiCert SHA2 Extended Validation Server CA
verify return:1
depth=0 businessCategory = Private Organization,
        jurisdictionC = US, jurisdictionST = Delaware,
        serialNumber = 5157550, street = "88 Colin P Kelly, Jr Street",
        postalCode = 94107, C = US, ST = California, L = San Francisco,
        O = "GitHub, Inc.", CN = github.com
verify return:1
---
Certificate chain
 0 s:/businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=Delaware/serialNumber=5157550/street=88 Colin P Kelly, Jr Street/postalCode=94107/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=github.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHeTCCB[...]
-----END CERTIFICATE-------

[...a bunch more stuff...]

Modern programming languages out there have a TLS library you could use to extract certificate info. If they don't, they sure have an OpenSSL wrapper that gets you there.

In Go, you'd use the crypto/tls package:

// PeerCertificate is of x509.Certificate type
conn.ConnectionState().PeerCertificates[0].Subject.CommonName

Here's Python (with M2Crypto):

>>> import ssl
>>> import M2Crypto
>>> cert = ssl.get_server_certificate(('github.com', 443))
>>> x509.get_subject().as_text()>>> x509 = M2Crypto.X509.load_cert_string(cert)
>>> x509.get_subject().as_text()
'businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=Delaware/
serialNumber=5157550/street=88 Colin P Kelly,
Jr Street/postalCode=94107, C=US, ST=California, L=San Francisco,
O=GitHub, Inc., CN=github.com'

>>> x509.get_issuer().as_text()
'C=US, O=DigiCert Inc, OU=www.digicert.com,
CN=DigiCert SHA2 Extended Validation Server CA'

>>> x509.get_fingerprint()
'B890FABE8BB63625899E1E0049814797'

# raw cert dump
>>> str(cert) 
'-----BEGIN CERTIFICATE-----\n
MIIHeTCCBmGgAwIBAgIQC/20CQrXteZAwwsW[...]\n
-----END CERTIFICATE-----\n'

In essense, it depends. The takeaway is TLS is not tied to HTTP at all (HTTP is Application Layer), TLS is lower in the OSI stack. HTTP starts to happen after TLS handshake has completed, so you don't have to do an HTTPS call to get the peer certificate, you just have to handshake TLS.

OSI model

(Click for image source)

Upvotes: 1

Related Questions