我創建了一個簡單的 Python 程式來獲取 SSL 證書的到期日期,來自 Internet 上的參考。它適用于仍未過期的證書。但是對于已經過期的證書,由于證書過期,在套接字握手期間引發了錯誤。
由于連接被拒絕,如何獲取過期的證書資訊以提取過期日期。即使證書可能已過期,是否有辦法強制建立套接字連接?
代碼:
import ssl
from cryptography import x509
import sys
import socket
hostname = sys.argv[1]
context = ssl.create_default_context()
with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print("SSL/TLS version:",ssock.version())
print()
data = ssock.getpeercert()
print("Data:",data)
print()
notafter_date = data["notAfter"]
print("Expiry date:",notafter_date)
print()
未過期證書的輸出:
$ python check_ssl_cert.py badssl.com
SSL/TLS version: TLSv1.2
Data: {'subject': ((('countryName', 'US'),), (('stateOrProvinceName', 'California'),), (('localityName', 'Walnut Creek'),), (('organizationName', 'Lucas Garron Torres'),), (('commonName', '*.badssl.com'),)), 'issuer': ((('countryName', 'US'),), (('organizationName', 'DigiCert Inc'),), (('commonName', 'DigiCert SHA2 Secure Server CA'),)), 'version': 3, 'serialNumber': '0AF06CDA37A60B641342F0A1EB1D59FD', 'notBefore': 'Mar 23 00:00:00 2020 GMT', 'notAfter': 'May 17 12:00:00 2022 GMT', 'subjectAltName': (('DNS', '*.badssl.com'), ('DNS', 'badssl.com')), 'OCSP': ('http://ocsp.digicert.com',), 'caIssuers': ('http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt',), 'crlDistributionPoints': ('http://crl3.digicert.com/ssca-sha2-g6.crl', 'http://crl4.digicert.com/ssca-sha2-g6.crl')}
Expiry date: May 17 12:00:00 2022 GMT
過期證書的輸出:
$ python check_ssl_cert.py expired.badssl.com
Traceback (most recent call last):
File "check_ssl_cert.py", line 11, in <module>
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
File "/usr/lib/python3.7/ssl.py", line 423, in wrap_socket
session=session
File "/usr/lib/python3.7/ssl.py", line 870, in _create
self.do_handshake()
File "/usr/lib/python3.7/ssl.py", line 1139, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1091)
正如其他解決方案所建議的那樣,它不能解決問題。
我試著換行
data = ssock.getpeercert()
到
data = ssock.getpeercert(True)
并且為未過期的證書回傳 DER 格式的證書,但對于已過期的證書出現證書驗證錯誤。
uj5u.com熱心網友回復:
我設法創建了一個可行的解決方案。在這里查看我的 Github 要點:https ://gist.github.com/sharuzzaman/8827ef0d9fff89e4e937579b2b01653f
還有這里的逐字代碼供快速參考
#!/bin/env python3
# check_ssl_cert.py - python get info for expired SSL cert
# Copyright 2022 Sharuzzaman Ahmat Raslan <[email protected]>
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along with this program. If not, see https://www.gnu.org/licenses/.
from cryptography import x509
import socket
import ssl
import sys
hostname = sys.argv[1]
# create default context
context = ssl.create_default_context()
# override context so that it can get expired cert
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print("SSL/TLS version:", ssock.version())
print()
# get cert in DER format
data = ssock.getpeercert(True)
print("Data:", data)
print()
# convert cert to PEM format
pem_data = ssl.DER_cert_to_PEM_cert(data)
print("PEM cert:", pem_data)
# pem_data in string. convert to bytes using str.encode()
# extract cert info from PEM format
cert_data = x509.load_pem_x509_certificate(str.encode(pem_data))
# show cert expiry date
print("Expiry date:", cert_data.not_valid_after)
print()
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/427962.html
標籤:Python python-3.x ssl
上一篇:從x509證書中獲取SCT串列
