python - 有没有简单的方法来检查网站是否有 SSL 证书

标签 python ssl

使用 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 the subject of the certificate. This information can be accessed with getpeercert() 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 - use https://www.debian-administration.org/ in HOST name. This site's certificate is not signed by any root certificates from cacerts.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/

相关文章:

c++ - SSL/TLS 协议(protocol)版本回退机制

java - 两个应用程序使用相同的 keystore 时,SSL握手异常

node.js - nodejs - 带有自签名证书的 UNABLE_TO_VERIFY_LEAF_SIGNATURE

python - 创建新列,其中两个不同数据帧的两列相同

python - python 开箱即用地支持什么样的客户端/服务器协议(protocol)?

java - 如何从 Android 执行 HTTPS POST?

c# - 如何在 MVC3 中使用 RequireHttps 属性指定不同的端口

python - 将 float 舍入为 x 位小数?

python - Keras 与 Caffe 中的卷积有什么区别?

python - 从python请求中的txt文件中的链接获取所有分页URL的列表