python SSL: CERTIFICATE_VERIFY_FAILED certificate has expired 证书错误的几种情况和解决方法
文章目錄
- 一、哪些情況可能會遇到這個錯誤?
- 二、為什么會出現(xiàn)這個錯誤?這個錯誤說明了什么?
-
- 2.1 HTTPS的簡要知識
- 2.2 客戶端是如何驗證服務(wù)器證書的呢?
-
- 2.2.1 常見的證書錯誤有:
- 三、哪些原因可能會導致證書錯誤?
-
- 3.1 證書無效報錯
-
- 3.1.1 網(wǎng)站使用自簽發(fā)證書
- 3.1.2 證書和域名不匹配
- 3.2 證書有效報錯
-
- 3.2.1 本地計算機缺少合適的根證書
- 3.2.2 本地計算機根證書過期未更新
- 3.2.3 證書鏈不完整
- 3.2.4 MacOS上python3沒有證書列表
- 3.2.5 解析證書的客戶端軟件問題
- 四、如何解決證書錯誤?
-
- 4.1 證書無效,替換有效證書
- 4.2 證書有效報證書驗證錯誤的幾種解決方案【重要】
-
- 4.2.1 MAC OS安裝python根CA證書列表
- 4.2.2 補全證書鏈
- 4.2.3 更新操作系統(tǒng)根證書庫
- 4.2.4 手動將證書添加到根CA證書列表【推薦】
- 4.2.5 手動指定根證書文件【推薦】
- 4.2.6 從其他證書提供機構(gòu)重新申請證書
- 4.3 屏蔽證書驗證【不推薦】
- 五、常見錯誤情況如何解決?
-
- 5.1 使用urllib或requests類庫,可以修改代碼
-
- 5.2 pip install安裝軟件時
- 5.3 setup.py upload上傳軟件包時
- 5.4 其他錯誤如何解決
- 六、更多問題
一、哪些情況可能會遇到這個錯誤?
- 使用urllib.request.urlopen請求https資源時(不限系統(tǒng))
- 使用requests的get或post方法請求https資源時(不限系統(tǒng))
- MAC OS中使用上面任意庫請求https資源時
- 使用pip install安裝軟件包時
- 使用setup.py upload 上傳軟件包到倉庫時
- 使用其他python腳本或命令,內(nèi)部使用了情況1或情況2的相關(guān)接口,訪問https資源時。
- 使用Python類庫請求一些https網(wǎng)站正常,請求另外一些https網(wǎng)站遇到這個錯誤
二、為什么會出現(xiàn)這個錯誤?這個錯誤說明了什么?
要想知道這個錯誤為什么會出現(xiàn),是什么導致了這個錯誤,需要簡單了解下SSL和證書的相關(guān)知識:
2.1 HTTPS的簡要知識
在HTTPS普及之前,大多數(shù)網(wǎng)站都使用明文傳輸?shù)腍TTP協(xié)議。用戶和網(wǎng)站的訪問內(nèi)容,密碼等在家庭路由器、小區(qū)交換機、公網(wǎng)節(jié)點等都是可以被中間人看到、攔截或修改的,即主要存在泄漏、篡改、假冒三大安全問題。
為了解決上面的安全問題,就需要對傳輸內(nèi)容進行加密,常規(guī)的加密算法包括對稱加密和非對稱加密,因為對稱加密存在秘鑰不便傳輸問題,HTTPS在連接的初始建立階段使用的是非對稱加密算法,加密連接創(chuàng)建后再切換到對稱加密算法提高性能。
非對稱加密的特點:
- 存在公鑰和私鑰兩個秘鑰,一般公鑰是任何人都可以拿到的。
- 公鑰加密的內(nèi)容可以用私鑰解密,反之亦然。
- 用公鑰或私鑰加密很簡單,但根據(jù)密文和公鑰破解私鑰很難。
HTTPS協(xié)議使用的是RSA非對稱加密技術(shù)。HTTPS通信流程如下:
- TCP三次握手
- 客戶端向服務(wù)器發(fā)起HTTPS請求
- 服務(wù)器返回數(shù)字證書
- 客戶端用本地內(nèi)置證書驗證服務(wù)器證書有效性,如果證書無效中斷整個流程;證書有效則生成隨機值作為對稱秘鑰,并使用證書加密對稱秘鑰;
- 客戶端把證書加密后的對稱秘鑰發(fā)送給服務(wù)器
- 服務(wù)器用私鑰解密獲得對稱秘鑰,再用對稱秘鑰加密內(nèi)容發(fā)給客戶端
- 客戶端收到服務(wù)器對稱加密的內(nèi)容,可以正確解密,至此加密連接創(chuàng)建完成。
流程3的服務(wù)器證書里面存儲的就是網(wǎng)站的公鑰。我們遇到的錯誤就是發(fā)生在流程4中,驗證證書無效。
更多關(guān)于HTTPS的知識
2.2 客戶端是如何驗證服務(wù)器證書的呢?
服務(wù)器的證書是包含了網(wǎng)站主要信息、公鑰、數(shù)字簽名等信息的一個文件。
非對稱加密只是確保了網(wǎng)絡(luò)連接的不被竊聽和篡改,但包含公鑰的證書是誰都可以簽發(fā)的,那拿到一個百度證書如何確定這個證書就是百度的證書呢?公鑰一般幾百上千個字符,全球十幾億個網(wǎng)站證書全都記錄下來也不現(xiàn)實,所以就提出了另一個概念:CA(Certificate Authority)證書簽發(fā)機構(gòu)。客戶端和服務(wù)器端都信任且保存了CA的證書,作為根證書;如果一個證書是由CA簽發(fā)的二級證書,那我們可以用CA的證書驗證它的有效性;如果服務(wù)器的證書是由驗證過的二級證書簽發(fā)的,那么我們也可以驗證服務(wù)器的證書的有效性;這樣的一個逐層驗證過程即形成了證書鏈。
根證書是直接保存在操作系統(tǒng)中的,凡是根證書直接或間接簽發(fā)的證書都可以信任;按這樣的原理,我們可以驗證成千上萬的網(wǎng)站證書是否有效;截止2020/08,MacOS內(nèi)置了168個根證書,Windows內(nèi)置了255個根證書,Chrome和FireFox使用自帶的證書庫。
需要注意的是,雖然操作系統(tǒng)內(nèi)置了根證書,但一些軟件可能并未使用系統(tǒng)根證書,而是在軟件安裝時自身帶了一些證書作為根證書。(如pythonpython的requests庫和pip等庫使用包內(nèi)置的根證書,有些瀏覽器也使用的內(nèi)置根證書而非系統(tǒng)根證書),如果電腦裝有everything,搜索cacert.pem可以發(fā)現(xiàn)很多文件,這些都是各個軟件自帶的根證書。
此外,**證書鏈可能不止一條!**計算機本地保存的根證書一般是幾十年有效期,由根證書頒發(fā)的二級證書一般是幾年有效期。如果你的電腦買了有兩三年了,有可能出現(xiàn)買的時候根證書還有效,現(xiàn)在根證書過期的情況,從而導致一些網(wǎng)站無法訪問。從瀏覽器訪問網(wǎng)站是按瀏覽器的根證書庫形成證書鏈,瀏覽器的根證書庫由瀏覽器維護和更新,所以一直顯示是正常的。而windows操作系統(tǒng)根證書庫由windows更新維護,python ssl使用的是操作系統(tǒng)的根證書庫,所以也可能出現(xiàn)瀏覽器中證書正常,python中報證書過期或無效問題。(PS:Windows10家庭版似乎沒有根證書自動更新。。)
雖然服務(wù)器部署證書的時候,一般都是部署的完整證書鏈,但客戶端不一定會使用網(wǎng)站提供的證書鏈;如果服務(wù)器證書鏈的根證書在客戶端本地根證書庫中不存在,客戶端就會從本地根證書庫中嘗試自己構(gòu)造一個可信的證書鏈,構(gòu)造過程中可能會使用過期的證書。
這是一個中間證書過期的例子
2.2.1 常見的證書錯誤有:
證書不可信(ERR_CERT_AUTHORITY_INVALID)【最多】
由不可信的CA機構(gòu)簽發(fā)的證書,比如自簽發(fā)的證書,或者操作系統(tǒng)缺失CA根證書。
證書名稱不匹配(ERR_CERT_COMMON_NAME_INVALID)
證書是簽發(fā)給www.baidu.com,但訪問的網(wǎng)站是baidu.com,也會出現(xiàn)這個問題。
證書過期(ERR_CERT_DATE_INVALID)
證書有效期到期,或本地時間不正確(根據(jù)行業(yè)標準,網(wǎng)站SSL證書有效期不能超過398天)
證書被吊銷(ERR_CERT_REVOKED)
虛假信息申請得到的證書,或私鑰被泄漏,或簽發(fā)錯誤等會出現(xiàn)這個情況
一般性SSL錯誤(ERR_SSL_PROTOCOL_ERROR)
證書部署錯誤,客戶端SSL協(xié)議不匹配,證書字段缺失等問題。
三、哪些原因可能會導致證書錯誤?
根據(jù)上面分析,造成證書錯誤的原因有很多,但籠統(tǒng)的可以分為兩類:證書無效報錯,證書有效報錯。
判斷網(wǎng)站證書是否有效建議通過myssl.com,輸入網(wǎng)站域名,可以測試出網(wǎng)站安全等級、支持的TLS版本、證書問題、支持瀏覽器版本等情況。
3.1 證書無效報錯
3.1.1 網(wǎng)站使用自簽發(fā)證書
自簽名的證書因為不是由根證書逐層簽發(fā)的,所以任意一臺電腦訪問這種網(wǎng)站時都會彈出連接不安全的警告。
現(xiàn)象:這個網(wǎng)站在任意一臺電腦訪問都會報證書錯誤。
3.1.2 證書和域名不匹配
證書分為單域名證書和通配符證書;單域名證書需要和網(wǎng)站域名完全匹配才能驗證通過,比如申請了www.baidu.com的單域名證書,部署在news.baidu.com上面就會出現(xiàn)證書名稱不匹配錯誤。通配符證書一般是針對主域名申請,如“*.baidu.com”,可以部署在其下所有子域名網(wǎng)站上。
3.2 證書有效報錯
3.2.1 本地計算機缺少合適的根證書
現(xiàn)象:其他電腦訪問此網(wǎng)站證書有效,此電腦報證書錯誤。(或通過myssl.com驗證網(wǎng)站證書有效)
3.2.2 本地計算機根證書過期未更新
現(xiàn)象:新電腦執(zhí)行python腳本或命令正常,此電腦瀏覽器訪問證書有效,python腳本顯示證書無效。
針對Python ssl的進一步排查方法:
- 查看當前python使用的openssl版本:
>>> import _ssl
>>> _ssl.OPENSSL_VERSION
'OpenSSL 1.1.1g 21 Apr 2020'
- 找到對應(yīng)Openssl程序
可通過everything搜索,按時間找到:
- 命令提示符打開,請求出錯的URL,查看證書鏈:
openssl s_client -showcerts -connect www.baidu.com:443
從顯示的證書鏈來看,第二個證書R3是let’s encrypt的根證書,第一個DSR Root證書確實于2021年9月到期了,過期了兩個月。
而瀏覽器查看網(wǎng)站的證書鏈,第一個證書的有效期是從2015年到2035年:
3.2.3 證書鏈不完整
現(xiàn)象:myssl.com驗證網(wǎng)站證書有效(提示證書鏈不完整),此電腦瀏覽器訪問網(wǎng)站證書有效,部分軟件請求網(wǎng)站證書錯誤。
3.2.4 MacOS上python3沒有證書列表
現(xiàn)象:python腳本訪問任何https網(wǎng)站均報證書錯誤。
3.2.5 解析證書的客戶端軟件問題
現(xiàn)象:通過myssl.com驗證網(wǎng)站證書有效,此電腦瀏覽器訪問網(wǎng)站證書有效,但python urlopen或requests訪問網(wǎng)站證書錯誤。
四、如何解決證書錯誤?
4.1 證書無效,替換有效證書
如果是自簽名證書或證書過期等情況,建議申請個有效的證書部署。
收費證書很多,可以找權(quán)威機構(gòu)購買;免費證書可以考慮:
- 申請let’s encrypt的三個月通配符證書;到期前需要重新申請并部署。
- 阿里云的一年SSL單域名證書,一年最多申請20個;過期前需要重新申請部署。
4.2 證書有效報證書驗證錯誤的幾種解決方案【重要】
4.2.1 MAC OS安裝python根CA證書列表
僅針對蘋果系統(tǒng)有效。
pip install --upgrade certifi
然后執(zhí)行文件:/Applications/Python\ 3.6/Install\ Certificates.command
4.2.2 補全證書鏈
上面我們提到,網(wǎng)站的證書是否有效是通過操作系統(tǒng)根證書逐層驗證的,如果系統(tǒng)缺失了對應(yīng)的根證書,就可能會出現(xiàn)網(wǎng)站在一些瀏覽器訪問正常,在其他客戶端(python腳本、微信瀏覽器等)報證書錯誤的現(xiàn)象。
如果myssl.com提示證書錯誤,可以按上面的修復(fù)工具連接,修復(fù)證書鏈不全問題。
證書鏈修復(fù)傳送門
一般修復(fù)前證書鏈有2個或三個證書,修復(fù)后會多一個;直接將修復(fù)后的證書鏈重新部署到服務(wù)器即可。
4.2.3 更新操作系統(tǒng)根證書庫
此方法可以解決部分證書錯誤,一些軟件包未使用系統(tǒng)根證書導致的錯誤仍然無法解決。
- 生成更新根證書列表文件:
D:/
certutil.exe -generateSSTFromWU roots.sst
- 從SST文件導入所有根證書,注意以管理員身份運行Powser Shell:
$sstStore = ( Get-ChildItem -Path D:\roots.sst )
$sstStore | Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root
- 重新進入【管理計算機證書】,查看根證書數(shù)量已從200+變成400+
更多關(guān)于更新windows證書的介紹
4.2.4 手動將證書添加到根CA證書列表【推薦】
此方法可解決幾乎全部使用python ssl包導致的證書錯誤問題。
此方法適用于客戶端較少的情況,如果很多客戶端都報證書錯誤,建議使用下一個方案。
查看python默認使用的根證書文件:
import ssl
ssl.get_default_verify_paths()> DefaultVerifyPaths(cafile='C:\\Program Files\\Common Files\\SSL/cert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='C:\\Program Files\\Common Files\\SSL/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='C:\\Program Files\\Common Files\\SSL/certs')
第一個cafile即當前使用的根證書列表文件,可以去看下這個文件是否存在。我們把證書內(nèi)容追加到這個文件末尾即可。
如果此文件不存在,可以使用everything搜索“cacert.pem”,找個文件作為默認根證書文件(一般最大的是比較全的),我這里是:C:\Users\lenovo\AppData\Local.certifi\cacert.pem,然后添加環(huán)境變量:SSL_CERT_FILE=新的根證書文件絕對路徑。
關(guān)閉命令提示符重新打開,再執(zhí)行上面命令,看到cafile變成了我們修改的值即可。
瀏覽器打開網(wǎng)站,點擊地址欄的鎖圖標,查看證書窗口,切換到證書路徑tab,點擊第一個根證書,查看證書,打開新證書窗口。
然后點擊詳細信息,復(fù)制到文件,導出證書文件。選擇Base64編碼X.509格式導出即可。
找到導出的文件,復(fù)制全部內(nèi)容。打開cafile路徑,黏貼到最后面,保存即可。
如果添加第一個證書后依然報證書錯誤,可以繼續(xù)添加第二個(即二級證書),第三個。我是添加第二個證書后不報錯了。
4.2.5 手動指定根證書文件【推薦】
如果客戶端代碼可以修改,可通過指定根證書的方式驗證指定網(wǎng)站的證書:
# urllib
import urllib
urllib.request.urlopen("https://example.com/some/info", cafile="ca.pem")# requests
requests.get('https://www.baidu.com', cert='ca.pem')
4.2.6 從其他證書提供機構(gòu)重新申請證書
證書有效,但報證書錯誤一般都是因為根證書或中間證書的缺失或過期。所以從其他證書機構(gòu)重新申請證書的話,對應(yīng)的根證書和中間證書會發(fā)生變化,自然可解決證書錯誤問題。
一般來說,越權(quán)威的證書機構(gòu),出現(xiàn)證書錯誤的可能性越小。
4.3 屏蔽證書驗證【不推薦】
適用于:證書有效報錯,證書無效報錯。
既然是證書驗證失敗導致的錯誤,當然可以跳過驗證環(huán)境,直接默認所有證書都有效,但這相當于恢復(fù)了HTTP,存在很大安全風險,如果可通過其他方法解決,盡量不要使用此方法。
屏蔽證書驗證也可以有很多級別,操作系統(tǒng)全局屏蔽,本進程屏蔽,本次請求屏蔽等。
屏蔽本次請求的證書驗證
# 針對urllib
import ssl
context = ssl._create_unverified_context()
urllib.urlopen('https://www.baidu.com', context=context)# 針對python3 urllib
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
urllib.urlopen('https://www.baidu.com', context=ctx)# 針對requests
requests.get('https://www.baidu.com', verify=False)
屏蔽本進程的證書驗證(一般用在進程啟動時)
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
屏蔽操作系統(tǒng)所有python進程的證書驗證(不推薦,疑似僅對python2生效)
設(shè)置環(huán)境變量:PYTHONHTTPSVERIFY=0
測試對python3.6, 3.8均不生效,疑似僅對python2生效。
五、常見錯誤情況如何解決?
上面提出了一些解決方法,但具體到各種場景,可能需要使用不同的方法。如果已確認證書有效,依然報證書錯誤,下面幾種情況可以考慮用對應(yīng)的方法:
5.1 使用urllib或requests類庫,可以修改代碼
建議使用手動指定根證書文件方法,簡單快速。
5.2 pip install安裝軟件時
可以通過pip install --trusted-host pypi.python.org [packagename] 的方式指定為信任站點
也可能是pip版本太低,pypi.python.org不支持TLS1.0和TLS1.1協(xié)議,也可以嘗試升級pip版本
5.3 setup.py upload上傳軟件包時
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1123)
如果部署了私有pip倉庫,通過https訪問,上傳軟件包時出現(xiàn)這個錯誤。因為內(nèi)部是setuptools調(diào)用的urllib,無法修改源代碼。建議使用手動將證書添加到根CA證書列表的方法。
我就是這種情況。部署的pip倉庫,瀏覽器訪問證書有效,通過let’s encrypt申請的通配符證書。但使用的conda python3.8環(huán)境,上傳軟件包時報證書錯誤。測試了在python3.7 3.8 3.9 3.10中均會報錯,在3.6中不報錯;搜索一些文檔說3.6的ssl驗證會更寬松一些。
我使用urllib單獨請求我的pip站點也復(fù)現(xiàn)了證書錯誤,但請求baidu.com證書沒問題;通過添加ISRG ROOT X1和R3的證書到根證書文件后這個錯誤沒有了。
5.4 其他錯誤如何解決
具體錯誤情況不同,可能的原因和解決方案也不相同,可以按是否能修改源代碼等情況,逐個嘗試上面的解決方法。
如果上面的方法都無法解決,建議優(yōu)先搜索Stack Overflow或者google上的相關(guān)資源。
百度上的相關(guān)文章大都類似,且不夠系統(tǒng)專業(yè),常見問題還好,一些不常見問題很難找到解決方案。
六、更多問題
系統(tǒng)中過期的證書可以刪除么?
永遠不要刪除過期證書,系統(tǒng)使用過期證書來保證向后兼容性,參考
免費證書和收費證書的區(qū)別
請看這篇文章
參考文章:
https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error
https://xiu2.net/it/details/6137680a61da421d645b8f01
https://coderedirect.com/questions/154225/certifacte-verify-failed-certificate-has-expired-ssl-c1108
http://woshub.com/updating-trusted-root-certificates-in-windows-10/
總結(jié)
以上是生活随笔為你收集整理的python SSL: CERTIFICATE_VERIFY_FAILED certificate has expired 证书错误的几种情况和解决方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python画统计图代码_Python使
- 下一篇: 英特尔想要乘上 AI 芯片的浪潮