17

I want the 'issued to' information from certificate in python. I try to use the SSL and SSLSocket library but did not happen.

enter image description here

Sid
  • 5,442
  • 2
  • 13
  • 18
Raj
  • 389
  • 1
  • 3
  • 10

4 Answers4

40

Updated answer

If you can establish a connection to the remote server you can use the ssl standard library module:

import ssl, socket

hostname = 'google.com'
ctx = ssl.create_default_context()
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
    s.connect((hostname, 443))
    cert = s.getpeercert()

subject = dict(x[0] for x in cert['subject'])
issued_to = subject['commonName']
issuer = dict(x[0] for x in cert['issuer'])
issued_by = issuer['commonName']

>>> issued_to
u'*.google.com'
>>> issued_by
u'Google Internet Authority G2'

Original answer

Use pyOpenSSL.

from OpenSSL import crypto

cert_file = '/path/to/your/certificate'
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cert_file).read())
subject = cert.get_subject()
issued_to = subject.CN    # the Common Name field
issuer = cert.get_issuer()
issued_by = issuer.CN

You can also access additional components, e.g. organisation (subject.O/issuer.O), organisational unit (subject.OU/issuer.OU).

Your certificate file might be in another format, so you could try crypto.FILETYPE_ASN1 instead of crypto.FILETYPE_PEM.

phoenix
  • 5,738
  • 3
  • 33
  • 41
mhawke
  • 80,261
  • 9
  • 108
  • 134
  • Thanks for reply.. I have tried this before but got ImportError: No module named cryptography.hazmat.bindings.openssl.binding and but tried to import it but looks very complex.. do you have any simpler method than this. @mhawke – Raj Jun 16 '15 at 10:08
  • It looks like you haven't properly installed pyOpenSSL. There are a number of dependencies which are missing. One of them is the `cryptography` package which is the one causing your error. You can install with `pip install pyopenssl` which should install the dependencies too, however, you might need a build environment. Your screenshot suggests a Windows environment - that might be more difficult to get going. – mhawke Jun 16 '15 at 12:33
  • 1
    I have updated my original answer with an alternative that relies only on the standard library `ssl` and `socket` modules. This method requires connecting to the remote server, which your acceptance of the `keytool` answer indicates is possible. I think this a better solution because it does not rely on an external tool (which you have to obtain/install/maintain), and it is based entirely on the standard library so it will be portable between OSes without worrying about dependencies. – mhawke Jun 16 '15 at 12:46
  • Thanks for the answer.. There were no method create_default_context() in python 2.7.6 , then i upgrade it to 2.7.9. and this code works. and yes for this i dont need to install any external tool .. thanks again !!! @mhawke – Raj Jun 17 '15 at 11:14
  • Hey! in most cases this works, although I get Timeouts on some sites, for example alipay.com:443, any ideas? – Matan Dobrushin Jan 04 '20 at 10:12
  • @MatanDobrushin: the site is not responsive. Try it from your browser: https://allpay.com. If you try [http://allpay.com](http://allpay.com) you'll see that the site is not operational. I doubt that they have any certificate installed there. – mhawke Jan 26 '21 at 11:54
2

If you use requests, a simple code is here:

#!/usr/bin/python
# -*- coding: utf-8 -*-


from requests.packages.urllib3.contrib import pyopenssl as reqs


def https_cert_subject_alt_names(host, port):
    """Read subject domains in https cert from remote server"""

    x509 = reqs.OpenSSL.crypto.load_certificate(
        reqs.OpenSSL.crypto.FILETYPE_PEM,
        reqs.ssl.get_server_certificate((host, port))
    )
    return reqs.get_subj_alt_name(x509)

if __name__ == '__main__':
    domains = https_cert_subject_alt_names("www.yahoo.com", 443)
    print(domains)

The result is as follow:

[('DNS', '*.www.yahoo.com'), 
 ('DNS', 'www.yahoo.com'), 
 ('DNS', 'add.my.yahoo.com'), 
 ('DNS', 'au.yahoo.com'), 
 ('DNS', 'be.yahoo.com'), 
 ('DNS', 'br.yahoo.com'), 
 ('DNS', 'ca.my.yahoo.com'), 
 ('DNS', 'ca.rogers.yahoo.com'), 
 ('DNS', 'ca.yahoo.com'), 
 ('DNS', 'ddl.fp.yahoo.com'), 
 ('DNS', 'de.yahoo.com'), 
 ...
 ('DNS', 'mbp.yimg.com')]
debug
  • 941
  • 8
  • 13
1

The pyOpenSSL library seems to be outdated and here is what they say in official docs

Note: The Python Cryptographic Authority strongly suggests the use of pyca/cryptography where possible.

there are some workarounds using Python's standard library, but most of those seem to be messy.

Here is the way to do it through pyca/cryptography. It looks pretty straightforward and clean

from cryptography.x509 import load_pem_x509_certificate

cert = load_pem_x509_certificate(certificate_content)
certificate_serial_number = cert.serial_number
certificate_issuer_info = cert.issuer.rfc4514_string()
certificate_subject_info = cert.subject.rfc4514_string()

the result will print the whole line with issuer details

CN=name,O=Org\, Inc.,L=Tucson,ST=Arizona,C=US
CN=Sectigo RSA Organization Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB

If you need any particular of the details, those are available through the attributes of cert.issuer object.

Henry Harutyunyan
  • 2,233
  • 1
  • 16
  • 21
-3

import os
import re
os.system('keytool -printcert -sslserver google.com:443 >cert.txt')
fh = open("cert.txt", "r")
content = fh.readlines()
fh.close()
content = content[2]
m = re.search('CN=(.+?),', content)
if m:
    found = m.group(1)
print found
  • thanks for reply.. could you please tell me, What is keytool? @pyAnna – Raj Jun 16 '15 at 10:09
  • keytool is a key and certificate management utility. It allows users to administer their own public/private key pairs and associated certificates for use in self-authentication (where the user authenticates himself/herself to other users/services) or data integrity and authentication services, using digital signatures. It also allows users to cache the public keys (in the form of certificates) of their communicating peers. – Tarun Venugopal Nair Jun 16 '15 at 10:17
  • Thanks @pyAnna after installing JDK the code has worked :) – Raj Jun 16 '15 at 10:57