36

How can I get the public key of a webpage like verisign , etc. using HTTPS protocol?

3
  • 3
    If I understand your question right then, you can click on the https protocol sign in chrome or firefox (on the left corner of the address bar), there you can see a pop showing detail about the certificate including its public key.
    – Jor-el
    Jun 15, 2012 at 18:43
  • @Jor-el, I'm assuming from the openssl tag that the question is about doing this with OpenSSL. Perhaps the question could be clarified.
    – Bruno
    Jun 15, 2012 at 20:06
  • An HTTPS page does not have a publickey; only a server has a publickey, and certificate for it, as explained in the answers. That is at least one domainname, and sometimes more than one. Different pages can't have different keys/certs, because the server must provide its cert (and the client accept it) before the client informs the server what page is requested -- if any; HTTP[S] allows requests that don't access any page at all. Oct 18, 2019 at 4:24

3 Answers 3

77

This command will show you the certificate (use -showcerts as an extra parameter if you want to see the full chain):

openssl s_client -connect the.host.name:443

This will get the certificate and print out the public key:

openssl s_client -connect the.host.name:443 | openssl x509 -pubkey -noout

If you want to dig further, this question might be of interest.

2
  • When running this on CentOS 7 with OpenSSL 1.0.2k, the command doesn't exit automatically after printing the key.
    – zymhan
    Apr 10, 2020 at 19:17
  • works on Qubes release 4.1.1, I can confirm; Oct 24, 2022 at 12:44
10

In google chrome, go to the https web page (say https://mail.google.com), click on the lock next to the URL, then click on "certificate information", click on the "Details" tab, and then find "Subject Public Key Info", which for mail.google.com says Subject Public Key Algorithm: "PKCS #1 RSA Encryption" and Subject's Public Key:

Modulus (1024 bits):
AF 39 15 98 68 E4 92 FE 4F 4F F1 BB FF 0D 2E B0
FE 25 AA BD 68 04 67 27 EA 6C 43 4C A7 6D CB C8
8F 7E 81 EE 87 26 25 10 12 54 33 9E AA 3D 9B 8F
8E 92 B3 4B 01 E3 F9 4A 29 C3 0F FD AC B7 D3 4C
97 29 3F 69 55 CF 70 83 04 AF 2E 04 6E 74 D6 0F
17 09 FE 9E 20 24 24 E3 C7 68 9C AC 11 BD 92 E4
B2 1B 09 F2 02 32 BB 55 1B 2D 16 5F 30 12 23 E2
4C 4A 8D C2 DA 3F E1 B8 BF F7 3A B1 86 BE F0 C5

Public Exponent (24 bits):
01 00 01

This corresponds to the decimal numbers N=123045765072979014913511278179231402316770142733119510397469126703890433473616878571037576880489731114142173557070569117331013682110047985574967516701153320350820086344743718518661070276817382223900929884490765709232088941906671668904441902033030813416432622693650320785674286428555963210887699747381872357573

and exponent=65537 used in RSA.

0

In Python 3, SSLSocket.getpeercert can be used to obtain the peer certificate, which in turn can be parsed by any DER certificate parser:

import ssl, socket
from asn1crypto import pem, x509

hostname = 'www.sjoerdlangkemper.nl'
ctx = ssl.create_default_context()
s = ctx.wrap_socket(socket.socket(), server_hostname=hostname)
s.connect((hostname, 443))
der = s.getpeercert(binary_form=True)
cert = x509.Certificate.load(der)
pubkey = cert.public_key.unwrap()
print(pubkey)

The variable pubkey is now a RSAPublicKey if the connection used RSA. You can get the modulus like this:

print(pubkey["modulus"].native)

Or convert it to a PEM public key like this:

print(pem.armor("PUBLIC KEY", pubkey.contents).decode("ASCII"))

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .