问题描述
我需要扫描 IP 列表并从该 IP 的证书中检索通用名称(对于每个允许端口 443 连接的 IP).我已经能够使用套接字和 ssl 模块成功地做到这一点.它适用于具有有效签名证书的所有 IP,但不适用于自签名证书.
如果我使用这种方法,它需要一个由我的 CA-bundle 验证的有效证书:
from socket 导入socket导入 ssls = 套接字()c = ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED, ca_certs='ca-bundle.crt')c.connect(('127.0.0.1', 443))打印 c.getpeercert()
如果我删除 cert_reqs=ssl.CERT_REQUIRED
然后它会连接但根本没有获得证书.
如何在 IP 上检索证书的通用名称,无论它是否针对 ca-bundle 进行验证?
python ssl 库似乎只有在具有有效签名的情况下才会为您解析证书.
"""返回数据的格式化版本SSL 通道另一端提供的证书.如果没有提供证书,则返回 None,如果是 {}已提供证书,但未验证."""
您仍然可以使用 ssl.get_server_certificate()
函数获取服务器证书,但它以 PEM 格式返回.(或者,您可以调用 c.getpeercert(True)
,它以二进制 DER 格式返回证书,无论是否经过验证.)
从这里开始,我将使用 M2Crypto 或 OpenSSL 来读取证书并获取值:
# M2Cryptocert = ssl.get_server_certificate(('www.google.com', 443))x509 = M2Crypto.X509.load_cert_string(cert)x509.get_subject().as_text()# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com'# OpenSSLx509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,证书)x509.get_subject().get_components()#[('C', '美国'),# ('ST', '加利福尼亚'),# ('L', '山景'),# ('O', 'Google Inc'),# ('CN', 'www.google.com')]
I need to scan through a list of IPs and retrieve the common name from the certificate on that IP (for every IP that allows port 443 connections). I have been able to successfully do this using the sockets and ssl modules. It works for all IPs with valid, signed certificates but it isn't working for self-signed certificates.
If I use this method, it requires a valid cert that is verified by my CA-bundle:
from socket import socket
import ssl
s = socket()
c = ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED, ca_certs='ca-bundle.crt')
c.connect(('127.0.0.1', 443))
print c.getpeercert()
If I remove the cert_reqs=ssl.CERT_REQUIRED
then it connects but doesn't get the certificate at all.
How can I retrieve the common name for a certificate on an IP whether it validates against the ca-bundle or not?
The python ssl library seems like it only parses out the cert for you if it has a valid signature.
"""Returns a formatted version of the data in the
certificate provided by the other end of the SSL channel.
Return None if no certificate was provided, {} if a
certificate was provided, but not validated."""
You can still get the server certificate with the ssl.get_server_certificate()
function, but it returns it in PEM format. (Alternatively, you could call c.getpeercert(True)
, which returns the cert in binary DER format, whether it's validated or not.)
>>> print ssl.get_server_certificate(('server.test.com', 443))
-----BEGIN CERTIFICATE-----
MIID4zCCAsugAwIBA.....
From here, I would use M2Crypto or OpenSSL to read the cert and get values:
# M2Crypto
cert = ssl.get_server_certificate(('www.google.com', 443))
x509 = M2Crypto.X509.load_cert_string(cert)
x509.get_subject().as_text()
# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com'
# OpenSSL
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
x509.get_subject().get_components()
#[('C', 'US'),
# ('ST', 'California'),
# ('L', 'Mountain View'),
# ('O', 'Google Inc'),
# ('CN', 'www.google.com')]
这篇关于如何使用 python 检索远程主机的 TLS/SSL 对等证书?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!