如何在 python 中获取证书颁发者信息?
How can i get Certificate issuer information in python?
我想要 python 中证书的 'issued to' 信息。我尝试使用 SSL 和 SSLSocket 库,但没有成功。
更新答案
如果可以建立到远程服务器的连接,则可以使用 ssl
标准库模块:
import ssl, socket
hostname = 'google.com'
ctx = ssl.create_default_context()
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
s.connect((hostname, 443))
cert = s.getpeercert()
subject = dict(x[0] for x in cert['subject'])
issued_to = subject['commonName']
issuer = dict(x[0] for x in cert['issuer'])
issued_by = issuer['commonName']
>>> issued_to
u'*.google.com'
>>> issued_by
u'Google Internet Authority G2'
原回答
使用pyOpenSSL。
from OpenSSL import crypto
cert_file = '/path/to/your/certificate'
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cert_file).read())
subject = cert.get_subject()
issued_to = subject.CN # the Common Name field
issuer = cert.get_issuer()
issued_by = issuer.CN
您还可以访问其他组件,例如组织 (subject.O
/issuer.O
),组织单位 (subject.OU
/issuer.OU
)。
您的证书文件可能是其他格式,因此您可以尝试 crypto.FILETYPE_ASN1
而不是 crypto.FILETYPE_PEM
。
import os
import re
os.system('keytool -printcert -sslserver google.com:443 >cert.txt')
fh = open("cert.txt", "r")
content = fh.readlines()
fh.close()
content = content[2]
m = re.search('CN=(.+?),', content)
if m:
found = m.group(1)
print found
如果你使用requests
,一个简单的代码在这里:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from requests.packages.urllib3.contrib import pyopenssl as reqs
def https_cert_subject_alt_names(host, port):
"""Read subject domains in https cert from remote server"""
x509 = reqs.OpenSSL.crypto.load_certificate(
reqs.OpenSSL.crypto.FILETYPE_PEM,
reqs.ssl.get_server_certificate((host, port))
)
return reqs.get_subj_alt_name(x509)
if __name__ == '__main__':
domains = https_cert_subject_alt_names("www.yahoo.com", 443)
print(domains)
结果如下:
[('DNS', '*.www.yahoo.com'),
('DNS', 'www.yahoo.com'),
('DNS', 'add.my.yahoo.com'),
('DNS', 'au.yahoo.com'),
('DNS', 'be.yahoo.com'),
('DNS', 'br.yahoo.com'),
('DNS', 'ca.my.yahoo.com'),
('DNS', 'ca.rogers.yahoo.com'),
('DNS', 'ca.yahoo.com'),
('DNS', 'ddl.fp.yahoo.com'),
('DNS', 'de.yahoo.com'),
...
('DNS', 'mbp.yimg.com')]
pyOpenSSL
库似乎已经过时,这是他们在官方文档中所说的
Note: The Python Cryptographic Authority strongly suggests the use of
pyca/cryptography where possible.
使用 Python 的标准库有一些变通方法,但其中大部分看起来很乱。
这是通过 pyca/cryptography 完成的方法。它看起来非常简单干净
from cryptography.x509 import load_pem_x509_certificate
cert = load_pem_x509_certificate(certificate_content)
certificate_serial_number = cert.serial_number
certificate_issuer_info = cert.issuer.rfc4514_string()
certificate_subject_info = cert.subject.rfc4514_string()
结果将打印整行发行人详细信息
CN=name,O=Org\, Inc.,L=Tucson,ST=Arizona,C=US
CN=Sectigo RSA Organization Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
如果您需要任何特定的细节,可以通过 cert.issuer
对象的属性获得。
我想要 python 中证书的 'issued to' 信息。我尝试使用 SSL 和 SSLSocket 库,但没有成功。
更新答案
如果可以建立到远程服务器的连接,则可以使用 ssl
标准库模块:
import ssl, socket
hostname = 'google.com'
ctx = ssl.create_default_context()
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
s.connect((hostname, 443))
cert = s.getpeercert()
subject = dict(x[0] for x in cert['subject'])
issued_to = subject['commonName']
issuer = dict(x[0] for x in cert['issuer'])
issued_by = issuer['commonName']
>>> issued_to
u'*.google.com'
>>> issued_by
u'Google Internet Authority G2'
原回答
使用pyOpenSSL。
from OpenSSL import crypto
cert_file = '/path/to/your/certificate'
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cert_file).read())
subject = cert.get_subject()
issued_to = subject.CN # the Common Name field
issuer = cert.get_issuer()
issued_by = issuer.CN
您还可以访问其他组件,例如组织 (subject.O
/issuer.O
),组织单位 (subject.OU
/issuer.OU
)。
您的证书文件可能是其他格式,因此您可以尝试 crypto.FILETYPE_ASN1
而不是 crypto.FILETYPE_PEM
。
import os
import re
os.system('keytool -printcert -sslserver google.com:443 >cert.txt')
fh = open("cert.txt", "r")
content = fh.readlines()
fh.close()
content = content[2]
m = re.search('CN=(.+?),', content)
if m:
found = m.group(1)
print found
如果你使用requests
,一个简单的代码在这里:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from requests.packages.urllib3.contrib import pyopenssl as reqs
def https_cert_subject_alt_names(host, port):
"""Read subject domains in https cert from remote server"""
x509 = reqs.OpenSSL.crypto.load_certificate(
reqs.OpenSSL.crypto.FILETYPE_PEM,
reqs.ssl.get_server_certificate((host, port))
)
return reqs.get_subj_alt_name(x509)
if __name__ == '__main__':
domains = https_cert_subject_alt_names("www.yahoo.com", 443)
print(domains)
结果如下:
[('DNS', '*.www.yahoo.com'),
('DNS', 'www.yahoo.com'),
('DNS', 'add.my.yahoo.com'),
('DNS', 'au.yahoo.com'),
('DNS', 'be.yahoo.com'),
('DNS', 'br.yahoo.com'),
('DNS', 'ca.my.yahoo.com'),
('DNS', 'ca.rogers.yahoo.com'),
('DNS', 'ca.yahoo.com'),
('DNS', 'ddl.fp.yahoo.com'),
('DNS', 'de.yahoo.com'),
...
('DNS', 'mbp.yimg.com')]
pyOpenSSL
库似乎已经过时,这是他们在官方文档中所说的
Note: The Python Cryptographic Authority strongly suggests the use of pyca/cryptography where possible.
使用 Python 的标准库有一些变通方法,但其中大部分看起来很乱。
这是通过 pyca/cryptography 完成的方法。它看起来非常简单干净
from cryptography.x509 import load_pem_x509_certificate
cert = load_pem_x509_certificate(certificate_content)
certificate_serial_number = cert.serial_number
certificate_issuer_info = cert.issuer.rfc4514_string()
certificate_subject_info = cert.subject.rfc4514_string()
结果将打印整行发行人详细信息
CN=name,O=Org\, Inc.,L=Tucson,ST=Arizona,C=US
CN=Sectigo RSA Organization Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
如果您需要任何特定的细节,可以通过 cert.issuer
对象的属性获得。