如何使用 python 解码 SSL 证书?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16899247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I decode a SSL certificate using python?
提问by puwei219
How can I decode a pem-encoded (base64) certificate with Python? For example this here from github.com:
如何使用 Python 解码 pem 编码(base64)证书?例如这里来自 github.com:
-----BEGIN CERTIFICATE-----
MIIHKjCCBhKgAwIBAgIQDnd2il0H8OV5WcoqnVCCtTANBgkqhkiG9w0BAQUFADBp
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSgwJgYDVQQDEx9EaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBDQS0xMB4XDTExMDUyNzAwMDAwMFoXDTEzMDcyOTEyMDAwMFowgcoxHTAb
BgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVT
MRswGQYLKwYBBAGCNzwCAQITCkNhbGlmb3JuaWExETAPBgNVBAUTCEMzMjY4MTAy
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2Fu
IEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRo
dWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7dOJw11wcgnz
M08acnTZtlqVULtoYZ/3+x8Z4doEMa8VfBp/+XOvHeVDK1YJAEVpSujEW9/Cd1JR
GVvRK9k5ZTagMhkcQXP7MrI9n5jsglsLN2Q5LLcQg3LN8OokS/rZlC7DhRU5qTr2
iNr0J4mmlU+EojdOfCV4OsmDbQIXlXh9R6hVg+4TyBkaszzxX/47AuGF+xFmqwld
n0xD8MckXilyKM7UdWhPJHIprjko/N+NT02Dc3QMbxGbp91i3v/i6xfm/wy/wC0x
O9ZZovLdh0pIe20zERRNNJ8yOPbIGZ3xtj3FRu9RC4rGM+1IYcQdFxu9fLZn6TnP
pVKACvTqzQIDAQABo4IDajCCA2YwHwYDVR0jBBgwFoAUTFjLJfBBT1L0KMiBQ5um
qKDmkuUwHQYDVR0OBBYEFIfRjxlu5IdvU4x3kQdQ36O/VUcgMCUGA1UdEQQeMByC
CmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMIGBBggrBgEFBQcBAQR1MHMwJAYI
KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBLBggrBgEFBQcwAoY/
aHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ0FDZXJ0cy9EaWdpQ2VydEhpZ2hBc3N1
cmFuY2VFVkNBLTEuY3J0MAwGA1UdEwEB/wQCMAAwYQYDVR0fBFowWDAqoCigJoYk
aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL2V2MjAwOWEuY3JsMCqgKKAmhiRodHRw
Oi8vY3JsNC5kaWdpY2VydC5jb20vZXYyMDA5YS5jcmwwggHEBgNVHSAEggG7MIIB
tzCCAbMGCWCGSAGG/WwCATCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGln
aWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCC
AVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABp
AGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBw
AHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQ
AC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQBy
AHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0
ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwBy
AHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBl
AG4AYwBlAC4wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBEGCWCGSAGG
+EIBAQQEAwIGwDAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcNAQEFBQADggEBABRS
cR+GnW01Poa7ZhqLhZi5AEzLQrVG/AbnRDnI6FLYERQjs3KW6RSUni8AKPfVBEVA
AMb0V0JC3gmJlxENFFxrvQv3GKNfZwLzCThjv8ESnTC6jqVUdFlTZ6EbUFsm2v0T
flkXv0nvlH5FpP06STLwav+JjalhqaqblkbIHOAYHOb7gvQKq1KmyuhUItnbKj1a
InuA6gcF1PnH8FNZX7t3ft6TcEFOI8t4eXnELurXZioY99HFfOISeIKNHeyCngGi
5QK+eKG5WVjFTG9PpTG0SVtemB4uOPYZxDmiSvt5BbjyWeUmEnCtwOh1Ix8Y0Qvg
n2Xkw9dJh1tybLEvrG8=
-----END CERTIFICATE-----
According to ssl-shopperit should be something like this:
根据ssl-shopper 的说法,它应该是这样的:
Common Name: github.com
Subject Alternative Names: github.com, www.github.com
Organization: GitHub, Inc.
Locality: San Francisco
State: California
Country: US
Valid From: May 26, 2011
Valid To: July 29, 2013
How can I get this plaintext using python?
如何使用 python 获取此明文?
采纳答案by zwol
Python's standard library, even in the latest version, does not include anything that can decode X.509 certificates. However, the add-on cryptographypackage does support this. Quoting an example from the documentation:
Python 的标准库,即使是最新版本,也不包含任何可以解码 X.509 证书的内容。但是,附加cryptography包确实支持这一点。引用文档中的一个例子:
>>> from cryptography import x509
>>> from cryptography.hazmat.backends import default_backend
>>> cert = x509.load_pem_x509_certificate(pem_data, default_backend())
>>> cert.serial_number
2
Another add-on package that might be an option is pyopenssl. This is a thin wrapper around the OpenSSL C API, which means it will be possibleto do what you want, but expect to spend a couple days tearing your hair out at the documentation.
另一个可能是一个选项的附加包是pyopenssl. 这是一个围绕 OpenSSL C API 的薄包装,这意味着它可以做你想做的事,但预计要花几天的时间来阅读文档。
If you can't install Python add-on packages, but you do have the opensslcommand-line utility,
如果您无法安装 Python 附加包,但您有openssl命令行实用程序,
import subprocess
cert_txt = subprocess.check_output(["openssl", "x509", "-text", "-noout",
"-in", certificate])
should produce roughly the same stuff you got from your web utility in cert_txt.
应该产生与您从cert_txt.
Incidentally, the reason doing a straight-up base64 decode gives you binary gobbledygook is that there are two layers of encoding here. X.509 certificatesare ASN.1data structures, serialized to X.690 DERformat and then, since DER is a binary format, base64-armored for ease of file transfer. (A lot of the standards in this area were written way back in the nineties when you couldn't reliably ship anything but seven-bit ASCII around.)
顺便说一句,直接进行 base64 解码为您提供二进制 gobbledygook 的原因是这里有两层编码。 X.509 证书是ASN.1数据结构,序列化为X.690 DER格式,然后,由于 DER 是二进制格式,base64-armored 以便于文件传输。(这个领域的很多标准都是在 90 年代写的,当时除了七位 ASCII 之外,你不能可靠地传送任何东西。)
回答by andviro
You can use pyasn1and pyasn1-modulespackages to parse this kind of data. For instance:
您可以使用pyasn1和pyasn1-modules包来解析此类数据。例如:
from pyasn1_modules import pem, rfc2459
from pyasn1.codec.der import decoder
substrate = pem.readPemFromFile(open('cert.pem'))
cert = decoder.decode(substrate, asn1Spec=rfc2459.Certificate())[0]
print(cert.prettyPrint())
Read the docs for pyasn1 for the rest.
阅读 pyasn1 的其他文档。
回答by CristiFati
Notes:
注意事项:
- Everything relies on (!!!undocumented!!!)
ssl._ssl._test_decode_cert
(present in Python 3(.7)/ Python 2), no additional module(s) needed - Please, take a look at [SO]: Can't receive peer certificate in Python client using OpenSSL's ssl.SSLContext() (@CristiFati's answer), which addresses a wider problem
- 一切都依赖于(!!!undocumented!!!)
ssl._ssl._test_decode_cert
(存在于Python 3(.7)/ Python 2 中),不需要额外的模块 - 请看一下[SO]: Can't receive peer certificate in Python client using OpenSSL's ssl.SSLContext() (@CristiFati's answer),它解决了一个更广泛的问题
Regarding the certificate (PEM) from the question:
关于问题中的证书(PEM):
- Saved it in a file called q016899247.crt(in the script (code00.py) dir)
- The end tag: ("-----END CERTIFICATE----") was missing a hyphen(-) at the end; corrected in Question @VERSION #4.)
- 将其保存在名为q016899247.crt的文件中(在脚本 ( code00.py) 目录中)
- 结束标记:(" -----END CERTIFICATE----" ) 在末尾缺少连字符( -);在问题@VERSION #4 中更正。)
code00.py:
code00.py:
#!/usr/bin/env python3
import sys
import os
import ssl
import pprint
def main():
cert_file_base_name = "q016899247.crt"
cert_file_name = os.path.join(os.path.dirname(__file__), cert_file_base_name)
try:
cert_dict = ssl._ssl._test_decode_cert(cert_file_name)
except Exception as e:
print("Error decoding certificate: {0:}".format(e))
else:
print("Certificate ({0:s}) data:\n".format(cert_file_base_name))
pprint.pprint(cert_dict)
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
Output:
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q016899247]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Certificate (q016899247.crt) data: {'OCSP': ('http://ocsp.digicert.com',), 'caIssuers': ('http://www.digicert.com/CACerts/DigiCertHighAssuranceEVCA-1.crt',), 'crlDistributionPoints': ('http://crl3.digicert.com/ev2009a.crl', 'http://crl4.digicert.com/ev2009a.crl'), 'issuer': ((('countryName', 'US'),), (('organizationName', 'DigiCert Inc'),), (('organizationalUnitName', 'www.digicert.com'),), (('commonName', 'DigiCert High Assurance EV CA-1'),)), 'notAfter': 'Jul 29 12:00:00 2013 GMT', 'notBefore': 'May 27 00:00:00 2011 GMT', 'serialNumber': '0E77768A5D07F0E57959CA2A9D5082B5', 'subject': ((('businessCategory', 'Private Organization'),), (('jurisdictionCountryName', 'US'),), (('jurisdictionStateOrProvinceName', 'California'),), (('serialNumber', 'C3268102'),), (('countryName', 'US'),), (('stateOrProvinceName', 'California'),), (('localityName', 'San Francisco'),), (('organizationName', 'GitHub, Inc.'),), (('commonName', 'github.com'),)), 'subjectAltName': (('DNS', 'github.com'), ('DNS', 'www.github.com')), 'version': 3} Done.
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q016899247]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Certificate (q016899247.crt) data: {'OCSP': ('http://ocsp.digicert.com',), 'caIssuers': ('http://www.digicert.com/CACerts/DigiCertHighAssuranceEVCA-1.crt',), 'crlDistributionPoints': ('http://crl3.digicert.com/ev2009a.crl', 'http://crl4.digicert.com/ev2009a.crl'), 'issuer': ((('countryName', 'US'),), (('organizationName', 'DigiCert Inc'),), (('organizationalUnitName', 'www.digicert.com'),), (('commonName', 'DigiCert High Assurance EV CA-1'),)), 'notAfter': 'Jul 29 12:00:00 2013 GMT', 'notBefore': 'May 27 00:00:00 2011 GMT', 'serialNumber': '0E77768A5D07F0E57959CA2A9D5082B5', 'subject': ((('businessCategory', 'Private Organization'),), (('jurisdictionCountryName', 'US'),), (('jurisdictionStateOrProvinceName', 'California'),), (('serialNumber', 'C3268102'),), (('countryName', 'US'),), (('stateOrProvinceName', 'California'),), (('localityName', 'San Francisco'),), (('organizationName', 'GitHub, Inc.'),), (('commonName', 'github.com'),)), 'subjectAltName': (('DNS', 'github.com'), ('DNS', 'www.github.com')), 'version': 3} Done.
回答by Roberto Mier
This code dumps a cert file content:
此代码转储证书文件内容:
import OpenSSL.crypto
cert = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM,
open('/path/to/cert/file.crt').read()
)
print OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_TEXT, cert)
Give it a go.
搏一搏。
回答by newbee
I am not Sure how you received it but another simple way for getting it installed is to just write it as a binary file and then run it using os
我不确定你是如何收到它的,但另一种安装它的简单方法是将它写成一个二进制文件,然后使用 os 运行它
import os
cert= function_gives_binary_cert()
with open('RecvdCert.der','wb') as file:
file.write(cert)
os.startfile('RecvdCert.der')
Beware of running received binary from an unknown source. Just want to decode then use OpenSSL as mentioned in other answers.
当心运行从未知来源收到的二进制文件。只想解码然后使用其他答案中提到的 OpenSSL。

