跳转至

python模拟浏览器验证证书

Python模拟浏览器验证证书

使用 Python 来模拟证书验证过程。Python 提供了多种库来帮助你验证证书的合法性,模拟 HTTPS 连接和执行证书验证的各个环节。以下是实现这个过程的一些关键步骤和相关库的使用方法。


1. 模拟证书验证的基本步骤

以下是模拟客户端验证服务器证书的主要步骤,你可以用 Python 来实现这些功能。

(1) 获取服务器证书

你可以使用 ssl 模块和 socket 模块从服务器获取其 SSL/TLS 证书。

import ssl
import socket

def get_server_certificate(hostname):
    # 创建SSL上下文
    context = ssl.create_default_context()

    # 使用socket连接服务器
    with socket.create_connection((hostname, 443)) as conn:
        with context.wrap_socket(conn, server_hostname=hostname) as ssl_socket:
            # 获取证书
            cert = ssl_socket.getpeercert()
            return cert

# 测试获取服务器证书
hostname = "www.example.com"
cert = get_server_certificate(hostname)
print(cert)

(2) 验证证书链

使用 ssl 模块的 ssl.create_default_context() 可以自动处理证书链的验证,验证服务器证书是否由可信的CA签发。

import ssl

def validate_certificate(hostname):
    context = ssl.create_default_context()

    # 客户端验证证书链
    try:
        context.check_hostname = True
        context.verify_mode = ssl.CERT_OPTIONAL  # 可选:要求验证证书的合法性
        with socket.create_connection((hostname, 443)) as conn:
            with context.wrap_socket(conn, server_hostname=hostname) as ssl_socket:
                cert = ssl_socket.getpeercert()
                print("证书验证通过")
                return cert
    except ssl.CertificateError as e:
        print(f"证书验证失败: {e}")
        return None

# 测试验证证书
hostname = "www.example.com"
cert = validate_certificate(hostname)

(3) 验证证书的有效期

证书中包含有效期信息,你可以从证书中提取该字段,并验证其是否在有效期内。

from datetime import datetime
import ssl

def check_certificate_validity(cert):
    # 获取证书的有效期
    notBefore = cert['notBefore']
    notAfter = cert['notAfter']

    # 转换为日期格式
    notBefore = datetime.strptime(notBefore, "%b %d %H:%M:%S %Y GMT")
    notAfter = datetime.strptime(notAfter, "%b %d %H:%M:%S %Y GMT")

    # 当前日期
    current_date = datetime.utcnow()

    if notBefore <= current_date <= notAfter:
        print("证书有效")
    else:
        print("证书过期")

# 从服务器获取证书并验证有效期
hostname = "www.example.com"
cert = get_server_certificate(hostname)
check_certificate_validity(cert)

(4) 验证域名是否匹配

验证证书中的域名是否与请求的服务器域名匹配。

import ssl
import socket

def verify_domain_match(cert, hostname):
    # 获取证书中的主机名(CN和SAN字段)
    subject = dict(x[0] for x in cert['subject'])
    common_name = subject.get('commonName', None)

    # 处理SAN(Subject Alternative Name)字段
    san = cert.get('subjectAltName', [])
    san_domains = [item[1] for item in san if item[0] == 'DNS']

    if common_name == hostname or hostname in san_domains:
        print("证书的域名与请求匹配")
    else:
        print("证书的域名与请求不匹配")

# 从服务器获取证书并验证域名匹配
hostname = "www.example.com"
cert = get_server_certificate(hostname)
verify_domain_match(cert, hostname)

(5) 吊销检查(CRL和OCSP)

吊销检查通常需要访问外部资源。如果你想模拟吊销检查,可以通过以下方式实现。

使用OCSP

可以使用 pyocspocsp 等 Python 库来查询证书的OCSP响应。

# 使用 pyocsp 或其他库查询证书的OCSP状态
import pyocsp

def check_ocsp(cert):
    ocsp_url = cert.get("OCSP", None)
    if ocsp_url:
        response = pyocsp.check_ocsp(ocsp_url, cert)
        if response:
            print("证书的吊销状态: ", response)
        else:
            print("无法获取OCSP响应")
CRL检查

你可以使用 cryptography 库来下载和检查证书的CRL列表。

from cryptography.x509 import load_pem_x509_certificate
from cryptography.x509.oid import NameOID
import requests

def check_crl(cert):
    crl_url = cert.extensions.get_extension_for_oid(NameOID.CRL_DISTRIBUTION_POINTS).value[0].full_name[0].value
    crl = requests.get(crl_url).content
    # 解析并检查CRL内容
    # 这里你可以使用cryptography库来解析并验证CRL

2. 完整的Python证书验证流程

你可以将上述步骤结合起来,创建一个完整的证书验证脚本,从服务器获取证书,验证签名、有效期、域名匹配等,并执行吊销检查。


3. 使用现有库简化过程

如果你不想手动实现所有的步骤,可以使用一些现有的库,像 requestspyOpenSSL,它们提供了更高层次的API来处理证书验证。

使用 requests

import requests

response = requests.get("https://www.example.com")
print(response.status_code)
requests 会自动处理 HTTPS 连接,并验证证书的合法性。如果证书无效,它会抛出 requests.exceptions.SSLError 错误。

使用 pyOpenSSL

from OpenSSL import SSL
import socket

def get_certificate(hostname):
    conn = SSL.Connection(SSL.Context(SSL.SSLv23_METHOD), socket.socket(socket.AF_INET, socket.SOCK_STREAM))
    conn.connect((hostname, 443))
    conn.do_handshake()
    cert = conn.get_peer_certificate()
    return cert

cert = get_certificate("www.example.com")
print(cert)

总结

用 Python 模拟证书验证过程是可行的,虽然你可以手动实现每个环节,但使用现有库如 sslrequestspyOpenSSL 可以大大简化工作。实现这些步骤将帮助你理解 SSL/TLS 验证过程的核心原理。