欢迎访问宙启技术站
智能推送

Python中ndg.httpsclient.ssl_peer_verification库下的SUBJ_ALT_NAME_SUPPORT功能详解

发布时间:2024-01-13 00:16:49

在Python中,ndg.httpsclient.ssl_peer_verification是一个用于增加OpenSSL SSL/TLS支持的第三方库。其中的SUBJ_ALT_NAME_SUPPORT功能是用于支持SSL证书的主题备用名称(subject alternative name)扩展。

SSL证书是用于加密和验证网络通信的安全协议。每个SSL证书都有一个 的主题备用名称,该名称指定了证书拥有者的身份。SUBJ_ALT_NAME_SUPPORT功能允许Python解析和验证主题备用名称,而不仅仅限于公共名称(common name)字段。

下面是一个使用ndg.httpsclient.ssl_peer_verification库下的SUBJ_ALT_NAME_SUPPORT功能的例子:

from OpenSSL import SSL
from socket import socket

from ndg.httpsclient.ssl_peer_verification import SUBJ_ALT_NAME_SUPPORT

def verify_hostname(cert, hostname):
    python_version = [int(v) for v in platform.python_version().split(".")]
    if python_version < [2, 7, 9]:
        raise ValueError("Hostname verification requires at least Python 2.7.9")
    if not SUBJ_ALT_NAME_SUPPORT:
        raise ValueError("Hostname verification requires ndg-httpsclient with subjectAltName support")

    peer_cert = cert.to_cryptography()
    try:
        peer_cert.verify_hostname(hostname)
    except Exception as e:
        raise ValueError("Hostname verification failed: %s" % e)

    return True

def create_ssl_ctx():
    ctx = SSL.Context(SSL.SSLv23_METHOD)
    ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_NO_COMPRESSION)
    # 允许使用主题备用名称验证
    ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_hostname)
    return ctx

def create_socket(host, port):
    sock = socket()
    sock.connect((host, port))
    sock_ssl = SSL.Connection(create_ssl_ctx(), sock)
    sock_ssl.set_connect_state()
    sock_ssl.do_handshake()
    return sock_ssl

if __name__ == '__main__':
    host = 'example.com'
    port = 443

    sock_ssl = create_socket(host, port)
    sock_ssl.sendall("GET / HTTP/1.1\r
Host: %s\r
\r
" % host)
    response = sock_ssl.recv(4096)
    sock_ssl.close()

    print(response)

在此例子中,我们创建了一个名为verify_hostname的函数来验证主题备用名称。我们使用了Python的cryptography库来解析证书并验证主题备用名称。如果验证失败,我们会抛出一个异常。

在create_ssl_ctx函数中,我们创建了一个SSL上下文,并通过设置set_verify函数启用了主题备用名称验证。

最后,在创建socket的函数中,我们使用create_ssl_ctx函数创建了一个加密的SSL连接,并发送了一个GET请求到指定的主机和端口。