Python如何获取服务端SSL证书及SSL证书验证步骤相关问题
getpeercert返回空的解决方法
你调用getpeercert返回空的核心原因是ssl.wrap_socket默认未开启证书验证,参数cert_reqs默认取值为ssl.CERT_NONE,该模式下SSL库不会留存对端证书信息,因此无论传入True还是False都会返回空字典。另外如果未指定server_hostname参数,对于部署了SNI的服务端也会出现拿不到证书的问题。
修复后的代码示例:
import socket import ssl import certifi s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 生成默认开启证书验证的上下文,内置信任certifi提供的根证书列表 ctx = ssl.create_default_context(cafile=certifi.where()) # 必须传入server_hostname适配SNI部署的站点 superSock = ctx.wrap_socket(s, server_hostname="www.google.com") superSock.connect(("www.google.com", 443)) # 不传参数/传True返回解析完成的证书字段字典,传False返回二进制DER格式证书 cert_info = superSock.getpeercert() print(cert_info) superSock.close()
SSL证书标准验证步骤
默认开启验证的情况下,会依次执行以下校验步骤,任意一步失败都会直接中断连接抛出错误:
- 证书链信任校验:提取服务端返回的完整证书链,从对应访问域名的叶子证书开始,逐层向上用上级证书的公钥验证当前证书的签名是否合法,直到匹配到本地存储的信任根证书锚点(即certifi模块内置的根证书列表)。
- 证书有效期校验:检查证书链上所有证书都处于签发时规定的有效期范围内,不存在过期、未到生效时间的情况。
- 域名匹配校验:验证叶子证书的使用者备用名称(SAN)字段或通用名称(CN)字段,和当前访问的域名匹配,泛域名证书需要符合对应的泛匹配规则。
- 撤销状态校验(可选):默认不会开启,手动开启后会通过CRL(证书撤销列表)或OCSP(在线证书状态协议)校验链上的证书是否已经被签发方提前撤销。
证书指纹相关说明
首先纠正一个认知偏差:证书指纹是整个DER格式证书文件的哈希值,并非仅从公钥生成。
- 标准签名验证阶段:不会固定使用SHA256或SHA1,而是读取证书内置的签名算法字段指定的哈希算法完成校验。由于SHA1存在严重的安全漏洞,目前主流CA已经停止签发SHA1签名的证书,现有生效证书几乎全部使用SHA256作为签名哈希算法。
- 自定义指纹校验:如果你需要额外做证书指纹比对,优先选择SHA256指纹,不要使用SHA1或MD5,后两者已经被证实存在哈希碰撞风险,不具备安全校验价值。你提到的base64编码内容是PEM格式证书的标准编码,解码后就是DER格式的原始证书,直接对DER内容做对应算法的哈希即可得到目标指纹。
内容的提问来源于stack exchange,提问作者Noob_learner_90
相关产品推荐
相关产品推荐

