Python使用ssl.getpeercert()从URL获取通用名称 [英] Python getting common name from URL using ssl.getpeercert()

查看:1390
本文介绍了Python使用ssl.getpeercert()从URL获取通用名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取证书颁发者信息(公用名),但链接中的代码不适用于某些网址。

I am trying to get Certificate issuer information (Common Name), but the code in the link doesn't work with some URLs.

我如何在python中获得证书颁发者信息?

import ssl, socket

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

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

>>> issued_to
u'*.google.com'

例如,我尝试过主机名cds .ca,它说

For example, I tried hostname "cds.ca", it says

ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)

但我仍然可以使用Internet Explorer(* .cds.ca)获取公用名称

but I could still get the Common name using Internet Explorer (*.cds.ca)

所以我认为我应该使用自己的证书(.cer)而不是使用getpeercert(),那么我该如何更改该行呢?

So I think I should use my own certificate(.cer) instead of using getpeercert(), then how should I change that line?

或者,有没有其他方法可以使用我自己的证书文件来实现CN?

Or, is there any other way to achieve CN with my own certificate file?

推荐答案

如果你只是想无论证书验证成功与否,都要获取CN或其他证书详细信息,您必须禁用验证。不幸的是,如果禁用证书验证,简单的 sock.getpeercert()将只返回一个空字典。这就是为什么必须使用 sock.getpeercert(True)来获取证书的二进制表示并使用OpenSSL.crypto从中提取CN:

If you just want to get the CN or other certificate details no matter if certificate validation succeeds or not, you have to disable the verification. Unfortunately a simple sock.getpeercert() will by design only return an empty dictionary if certificate validation is disabled. That's why one has to use sock.getpeercert(True) to get the binary representation of the certificate and extract the CN using OpenSSL.crypto from it:

import socket
import ssl
import OpenSSL.crypto as crypto

dst = ('cds.ca',443)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(dst)

# upgrade the socket to SSL without checking the certificate
# !!!! don't transfer any sensitive data over this socket !!!!
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
s = ctx.wrap_socket(s, server_hostname=dst[0])

# get certificate
cert_bin = s.getpeercert(True)
x509 = crypto.load_certificate(crypto.FILETYPE_ASN1,cert_bin)
print("CN=" + x509.get_subject().CN)

这篇关于Python使用ssl.getpeercert()从URL获取通用名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆