我正在尝试获取证书颁发者信息(通用名称),但链接中的代码不适用于某些 URL。
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'
Run Code Online (Sandbox Code Playgroud)
例如,我试过主机名“cds.ca”,它说
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)
Run Code Online (Sandbox Code Playgroud)
但我仍然可以使用 Internet Explorer (*.cds.ca) 获取通用名称
所以我想我应该使用我自己的证书(.cer)而不是使用 getpeercert(),那么我应该如何更改该行?
或者,有没有其他方法可以用我自己的证书文件实现CN?
如果无论证书验证成功与否,您只想获取 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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3557 次 |
| 最近记录: |