我正在尝试获取证书颁发者信息(公用名),但链接中的代码不适用于某些网址。
How can i get Certificate issuer information in 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",它说
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)
但我仍然可以使用Internet Explorer(* .cds.ca)获取公用名称
所以我认为我应该使用自己的证书(.cer)而不是使用getpeercert(),那么我该如何更改该行呢?
或者,有没有其他方法可以使用我自己的证书文件来实现CN?
答案 0 :(得分:2)
如果您只想获取CN或其他证书详细信息,无论证书验证成功与否,您都必须禁用验证。不幸的是,如果禁用证书验证,简单的sock.getpeercert()
将仅返回空字典。这就是为什么必须使用sock.getpeercert(True)
获取证书的二进制表示并使用OpenSSL.crypto从中提取CN的原因:
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)