python 指定证书验证_Python通过OpenSSL获取指定域名对应的SSL证书

同一台服务器上配置了不同的虚拟主机域名证书也可以获取到,直接上代码了:

def get_certificate(hostname, port):

import idna

from socket import socket

from OpenSSL import SSL

sock = socket()

# sock.settimeout(10) # 不要开启

sock.setblocking(True) # 关键。。

sock.connect((hostname, port), )

ctx = SSL.Context(SSL.SSLv23_METHOD)

ctx.check_hostname = False

ctx.verify_mode = SSL.VERIFY_NONE

sock_ssl = SSL.Connection(ctx, sock)

sock_ssl.set_tlsext_host_name(idna.encode(hostname)) # 关键: 对应不同域名的证书

sock_ssl.set_connect_state()

sock_ssl.do_handshake()

cert = sock_ssl.get_peer_certificate()

sock_ssl.close()

sock.close()

return cert

for u in ['https://www.baidu.com/', 'https://mp.weixin.qq.com/', 'https://www.qq.com/']:

from urllib import parse

rs = parse.urlparse(u)

cert = get_certificate(rs.hostname, int(rs.port or 443))

print(u)

print('\ttime:', cert.get_notBefore(), '~', cert.get_notAfter())

需注意的是如果设置了超时(sock.settimeout(10))打开了了非阻塞模式,有可能出现下面的错误(用sock.setblocking(True)启用阻塞模式):

Traceback (most recent call last):

File "webcheck.py", line 122, in main

cert = get_certificate(rs.hostname, int(rs.port or 443))

File "webcheck.py", line 23, in get_certificate

sock_ssl.do_handshake()

File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/OpenSSL/SSL.py", line 1915, in do_handshake

self._raise_ssl_error(self._ssl, result)

File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/OpenSSL/SSL.py", line 1622, in _raise_ssl_error

raise WantReadError()

WantReadError