我正试图找到一种从给定证书中获取SAN列表的方法,但是,我在pyOpenSSL文档中找不到任何内容。
有关如何从证书中提取此数据的任何想法?
答案 0 :(得分:2)
使用recommends的PyOpenSSL cryptography
,因为它提供了更安全,更好的API。如果您可以安装加密技术(它是requests
库的依赖项,那么已经安装了许多项目),这是获取SAN的方法:
from cryptography import x509
# classes must be subtype of:
# https://cryptography.io/en/latest/x509/reference/#cryptography.x509.ExtensionType
san = loaded_cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
print(san)
这是从主机检索证书并打印其通用名称和SAN的完整示例。
import ssl
from cryptography import x509
from cryptography.hazmat.backends import default_backend
certificate: bytes = ssl.get_server_certificate(('example.com', 443)).encode('utf-8')
loaded_cert = x509.load_pem_x509_certificate(certificate, default_backend())
common_name = loaded_cert.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)
print(common_name)
# classes must be subtype of:
# https://cryptography.io/en/latest/x509/reference/#cryptography.x509.ExtensionType
san = loaded_cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
san_dns_names = san.value.get_values_for_type(x509.DNSName)
print(san_dns_names)
或者,如果您要从主机下载证书,则Python的内置ssl
库将为您解析SAN:
from collections import defaultdict
import socket
import ssl
hostname = 'www.python.org'
context = ssl.create_default_context()
with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
# https://docs.python.org/3/library/ssl.html#ssl.SSLSocket.getpeercert
cert = ssock.getpeercert()
subject = dict(item[0] for item in cert['subject'])
print(subject['commonName'])
subjectAltName = defaultdict(set)
for type_, san in cert['subjectAltName']:
subjectAltName[type_].add(san)
print(subjectAltName['DNS'])
答案 1 :(得分:1)
我找到了一种方法,我们首先按名称检查扩展名,然后,当" SAN"数据发现我们得到str
表示并返回。
def get_certificate_san(x509cert):
san = ''
ext_count = x509cert.get_extension_count()
for i in range(0, ext_count):
ext = x509cert.get_extension(i)
if 'subjectAltName' in str(ext.get_short_name()):
san = ext.__str__()
return san
答案 2 :(得分:0)
我做了一些挖掘,我终于找到了一些东西,如果其他人需要答案:
<button onclick="new thing()">Create a new thing!</button>
答案 3 :(得分:0)
基于@anatolii-chmykhalo 的回答
这将根据字符串表示返回 DNS 的替代名称。
def get_dns_altnames(req: OpenSSL.crypto.X509Req):
"""
Get DNS altnames from a X509Req certificate
"""
extensions = (ext for ext in req.get_extensions()
if ext.get_short_name() == b'subjectAltName')
dns_names = []
for ext in extensions:
for alt in str(ext).split(', '):
if alt.startswith('DNS:'):
dns_names.append(alt[4:])
return dns_names