使用 urllib2/SSL?
我有一个很大的域列表,了解是否有我不知道的 ssl 证书会很有用。
最佳答案
我不确定是否使用urllib2
。不幸的是,我能找到的最接近的信息是 this link以及相关代码:
import socket
import ssl
HOST = "www.google.com"
PORT = 443
# replace HOST name with IP, this should fail connection attempt
HOST = socket.getaddrinfo(HOST, PORT)[0][4][0]
print(HOST)
# create socket and connect to server
# server address is specified later in connect() method
sock = socket.socket()
sock.connect((HOST, PORT))
# wrap socket to add SSL support
sock = ssl.wrap_socket(sock,
# flag that certificate from the other side of connection is required
# and should be validated when wrapping
cert_reqs=ssl.CERT_REQUIRED,
# file with root certificates
ca_certs="cacerts.txt"
)
# security hole here - there should be an error about mismatched host name
# manual check of hostname
cert = sock.getpeercert()
for field in cert['subject']:
if field[0][0] == 'commonName':
certhost = field[0][1]
if certhost != HOST:
raise ssl.SSLError("Host name '%s' doesn't match certificate host '%s'"
% (HOST, certhost))
虽然文件中的注释相当广泛,但第一个链接中的 wiki 还列出了这些说明:
To validate that a certificate matches requested site, you need to check
commonName
field in thesubject
of the certificate. This information can be accessed withgetpeercert()
method of wrapped socket.You will need
cacerts.txt
file that contains root certificates placed alongside the script - see below how to get an updated list. To check that certificate validation works - usehttps://www.debian-administration.org/
inHOST
name. This site's certificate is not signed by any root certificates fromcacerts.txt
, so you will get an error.
您可以查看 pyopenssl module另外,根据我发布的第一个链接,它可以用于以这种方式验证 SSL 证书:
import socket
from OpenSSL import SSL
HOST = "www.google.com"
PORT = 443
# replace HOST name with IP, this should fail connection attempt,
# but it doesn't by default
HOST = socket.getaddrinfo(HOST, PORT)[0][4][0]
print(HOST)
# uses HOST
def verify_cb(conn, x509, errno, errdepth, retcode):
"""
callback for certificate validation
should return true if verification passes and false otherwise
"""
if errno == 0:
if errdepth != 0:
# don't validate names of root certificates
return True
else:
if x509.get_subject().commonName != HOST:
return False
else:
return False
context = SSL.Context(SSL.SSLv23_METHOD)
context.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
context.load_verify_locations("cacerts.txt")
# create socket and connect to server
sock = socket.socket()
sock = SSL.Connection(context, sock)
sock.connect((HOST, PORT))
sock.do_handshake()
根据第一个链接中的文档,您将需要 here 中的最新证书版本对于这些示例。
关于python - 有没有简单的方法来检查网站是否有 SSL 证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9099349/