如何使用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-----
根据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
如何使用python获取此纯文本?
答案 0 :(得分:32)
Python的标准库,即使在最新版本中,也不包含任何可以解码X.509证书的内容。但是,附加组件cryptography
确实支持此功能。引用example from the documentation:
>>> 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
另一个可能是选项的附加软件包是pyopenssl
。这是一个围绕OpenSSL C API的瘦包装,这意味着它可能可能做你想做的事情,但是希望花几天时间在文档上撕掉你的头发。
如果您无法安装Python附加软件包,但您确实拥有openssl
命令行实用程序,
import subprocess
cert_txt = subprocess.check_output(["openssl", "x509", "-text", "-noout",
"-in", certificate])
应该生成与cert_txt
中的Web实用程序大致相同的内容。
顺便说一句,做直接base64解码的原因给你二进制gobbledygook是这里有两层编码。 X.509 certificates是ASN.1数据结构,序列化为X.690 DER格式,然后,由于DER是二进制格式,因此基于64位文件,以便于文件传输。 (这个领域的很多标准都是在九十年代写的,当时你无法可靠地发送除七位ASCII以外的任何东西。)
答案 1 :(得分:27)
您可以使用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())
阅读其余的pyasn1文档。
答案 2 :(得分:8)
备注强>:
ssl._ssl._test_decode_cert
关于问题的证书( PEM ):
code.py :
#!/usr/bin/env python3
import sys
import os
import ssl
from pprint import pprint as pp
def main():
cert_file_name = os.path.join(os.path.dirname(__file__), "q016899247.crt")
try:
cert_dict = ssl._ssl._test_decode_cert(cert_file_name)
pp(cert_dict)
except Exception as e:
print("Error decoding certificate: {:}".format(e))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
<强>输出强>:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q016899247]> "e:\Work\Dev\VEnvs\py_064_03.07.02_test0\Scripts\python.exe" code.py Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] on win32 {'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}
答案 3 :(得分:1)
You can download the code from here。它纯粹是从 .pem 和 .cer 类型证书中提取数据。
否则,可以使用以下代码段解码 pem 证书:
#import pem & pyOpenSSL module
certs = pem.parse_file(file_path) # using pem module
for pem_certificates in certs:
strcert = str(pem_certificates)
loadCert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,strcert)
print(loadCert.get_issuer())```
答案 4 :(得分:1)
这允许从 SSL 证书中提取某些值:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
hostname = 'google.com.com'
port = 443
ert = ssl.get_server_certificate((hostname, port))
certDecoded = x509.load_pem_x509_certificate(str.encode(cert),
default_backend())
print(certDecoded.issuer)
print(certDecoded.subject)
print(certDecoded.not_valid_after)
print(certDecoded.not_valid_before)
答案 5 :(得分:0)
此代码转储证书文件内容:
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)
试试吧。
答案 6 :(得分:0)
我不确定您是如何收到它的,但是另一种简单的安装方法是将其写入二进制文件,然后使用os运行它。
import os
cert= function_gives_binary_cert()
with open('RecvdCert.der','wb') as file:
file.write(cert)
os.startfile('RecvdCert.der')
当心运行从未知来源收到的二进制文件。只是想解码,然后使用其他答案中提到的OpenSSL。
答案 7 :(得分:0)
还有另一种无需使用内部实现即可使用 _test_decode_certificate
的方法。虽然以不同的方式有点hacky
import ssl
ctx = ssl.SSLContext()
# The filepath to your PEM-encoded x509 cert
ctx.load_verify_locations("369fa1ef21f5476c02814c637d83f71d851f867348eef21d1eb0058671d0e5a6.crt")
certificate_details = ctx.get_ca_certs()
在幕后,这是 _decode_certificate
使用的 _test_decode_certificate
函数的另一个入口点。
您可以在 CPython 源代码中看到它是如何工作的https://github.com/python/cpython/blob/main/Modules/_ssl.c#L4578