# solve : [SSL: CERTIFICATE_VERIFY_FAILED]
>本次的主題說明若 Mac 用戶無法在 python 裡取得 https 網址的相關資料時,會造成此結果的原因為何?該如何解決?以及相關名詞解釋。
## CERTIFICATE 是什麼?
certificate 中文叫做憑證,它的功能就像日常生活裡的入場券、身分證等的功能一樣,有了 certificate 可以讓對方知道我們的身份是否符合標準。
### SSL 與 CERTIFICATE
就像剛剛所提到,不同場合有不同憑證:去遊樂園要看門票、乘坐高鐵某個位置會需要對號座車票、刷卡進系館要學生證 ⋯⋯ 這次主題所著重要提的是針對 SSL 的憑證,也就是 SSL CERTIFICATE。
在網路協定中,SSL certificate 是用來驗證網站身份,以確保網站的安全性和真實性,那什麼是 SSL 呢?
### SSL 與 HTTPS
SSL 的存在區分了我們所謂的 HTTP 和 HTTPS。在[aws官網](https://aws.amazon.com/tw/compare/the-difference-between-https-and-http/)中,HTTPS 的敘述如下:
>*"HTTPS websites must obtain an SSL/TLS certificate from an independent certificate authority (CA). These websites share the certificate with the browser before exchanging data to establish trust. The SSL certificate also contains cryptographic information, so the server and web browsers can exchange encrypted or scrambled data."*
>
>[name=aws]
>

透過 SSL 加密,傳輸的資料就不會被第三方截取,也就加強了網頁的安全性。關於瀏覽器和 Web 伺服器安全交換訊息的過程如下:
1. 在瀏覽器網址列中輸入 https:// 格式的 URL,來造訪 HTTPS 網站。
2. 瀏覽器嘗試請求伺服器的 SSL certificate,來驗證網站的真實性。
3. 伺服器會傳送包含公有金鑰的 SSL/TLS certificate 來做為回覆。
4. 網站的 SSL certificate 可證明伺服器身分。滿足瀏覽器的要求後,即會使用公有金鑰來加密和傳送包含機密工作階段金鑰的訊息。
5. Web 服務器使用其私鑰來解密消息並檢索會話密鑰。然後,它會加密工作階段金鑰,並將確認訊息傳送至瀏覽器。
SSL 在瀏覽器和網路伺服器之間建立了加密和安全的連線,因此使用者傳送和接收的所有資料都使用公鑰和私鑰加密。
介紹完了 SSL 和憑證,接下來就要說明這次主題所要探討的問題,以及如何解決。
## problem : [SSL: CERTIFICATE_VERIFY_FAILED]
我在執行下列程式時出現上述問題。
```py=
def show_image(image_path):
if "http" in image_path:
image_path = image_utils.get_file(origin=image_path)
image = mpimg.imread(image_path)
print(image.shape)
plt.imshow(image)
show_image(
"https://cdn.britannica.com/02/152302-050-1A984FCB/African-savanna-elephant.jpg"
)
```
顯示的詳細錯誤訊息和[這個討論串](https://github.com/ageron/handson-ml/issues/46)非常類似,實際訊息如下:
```
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/urllib/request.py:1346, in AbstractHTTPHandler.do_open(self, http_class, req, **http_conn_args)
1345 try:
-> 1346 h.request(req.get_method(), req.selector, req.data, headers,
1347 encode_chunked=req.has_header('Transfer-encoding'))
1348 except OSError as err: # timeout error
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1285, in HTTPConnection.request(self, method, url, body, headers, encode_chunked)
1284 """Send a complete request to the server."""
-> 1285 self._send_request(method, url, body, headers, encode_chunked)
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1331, in HTTPConnection._send_request(self, method, url, body, headers, encode_chunked)
1330 body = _encode(body, 'body')
-> 1331 self.endheaders(body, encode_chunked=encode_chunked)
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1280, in HTTPConnection.endheaders(self, message_body, encode_chunked)
1279 raise CannotSendHeader()
-> 1280 self._send_output(message_body, encode_chunked=encode_chunked)
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1040, in HTTPConnection._send_output(self, message_body, encode_chunked)
1039 del self._buffer[:]
-> 1040 self.send(msg)
1042 if message_body is not None:
1043
...
--> 295 raise Exception(error_msg.format(origin, e.errno, e.reason))
296 except (Exception, KeyboardInterrupt):
297 if os.path.exists(fpath):
Exception: URL fetch failure on https://th.bing.com/th/id/OIP.040FghmKsQOaKUAJUAMhxwHaEo?rs=1&pid=ImgDetMain: None -- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
```
這個問題是出自於我要拜訪 HTTPS 的網站,然而 Mac 在我所使用的 python 3.9.12 中並沒有開啟 SSL 的 certificate。因此我們的解決方法就是去開啟 SSL 的 certificate。
## 解決方法
到 `python.framework` 底下找到對應版本的資料夾,並開啟名為 `Install Certificates.command`的檔案。

若找不到可以直接用指令打開:
``` =
open /Applications/Python\ 3.9/Install\Certificates.command
```
若沒有下載相關 package 可能會出現以下內容。遇到這種狀況只要去把缺少的補下載就好。
```
/Applications/Python\ 3.9/Install\ Certificates.command ; exit;
xxx@xxx ~ % /Applications/Python\ 3.9/Install\ Certificates.command ; exit;
-- pip install --upgrade certifi
Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (2022.9.24)
Collecting certifi
Using cached certifi-2024.2.2-py3-none-any.whl.metadata (2.2 kB)
Using cached certifi-2024.2.2-py3-none-any.whl (163 kB)
Installing collected packages: certifi
Attempting uninstall: certifi
Found existing installation: certifi 2022.9.24
Uninstalling certifi-2022.9.24:
Successfully uninstalled certifi-2022.9.24
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
tensorflow 2.16.1 requires wrapt>=1.11.0, which is not installed.
Successfully installed certifi-2024.2.2
-- removing any existing file or link
-- creating symlink to certifi certificate bundle
-- setting permissions
-- update complete
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
Deleting expired sessions... 8 completed.
[程序完成]
```
成功的話會顯示:
```
Last login: Mon Apr 8 14:13:54 on ttys010
/Applications/Python\ 3.9/Install\ Certificates.command ; exit;
xxx@xxx ~ % /Applications/Python\ 3.9/Install\ Certificates.command ; exit;
-- pip install --upgrade certifi
Requirement already satisfied: certifi in /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages (2024.2.2)
-- removing any existing file or link
-- creating symlink to certifi certificate bundle
-- setting permissions
-- update complete
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
```
之後就可以使用 python 取得 https 的檔案了!
## ref
- [github 討論串](https://github.com/ageron/handson-ml/issues/46)
- [github 討論串2](https://github.com/fchollet/deep-learning-models/issues/33)
- [Scraping: SSL: CERTIFICATE_VERIFY_FAILED error for http://en.wikipedia.org [duplicate]](https://stackoverflow.com/questions/50236117/scraping-ssl-certificate-verify-failed-error-for-http-en-wikipedia-org)
- [aws](https://aws.amazon.com/compare/the-difference-between-https-and-http/?nc1=h_ls)
- [圖片](https://www.websitebuilderexpert.com/building-websites/what-is-an-ssl-certificate/)