使用Python v3.4 + SSLContext 進行SSL / TLS客戶端證書驗證

2022-01-10 51reboot運維開發

Python第 19 期、自動化第 8 期正在火熱招生中

小夥伴們可以點擊諮詢

通常,SSL / TLS 客戶端會驗證伺服器的證書。伺服器也可能需要客戶端的籤名證書。這些被稱為客戶證書。這確保了客戶端不僅可以信任伺服器,而且伺服器也可以信任客戶端。

傳統上在 Python 中,您需要將 ca_certs 參數傳遞給 ssl.wrap_socket() 伺服器上的函數以啟用客戶端證書:

#客戶端
ssl.wrap_socket(s,ca_certs =「ssl / server.crt」,cert_reqs = ssl.CERT_REQUIRED,
               certfile =「ssl / client.crt」,keyfile =「ssl / client.key」)

#伺服器
ssl.wrap_socket(connection,server_side = True,certfile =「ssl / server.crt」,
               keyfile =「ssl / server.key」,ca_certs =「ssl / client.crt」)

自從 Python v3.4 以來,在 SSL / TLS 層中封裝套接字的更安全且更  優選的方法是創建SSLContext實例和調用SSLContext.wrap_socket()。但是,該SSLContext.wrap_socket()方法沒有 ca_certs參數。如何在伺服器端啟用客戶端證書的要求也不是很明顯。

文檔 SSLContext.load_default_certs() 中提到了客戶端證書:

Purpose.CLIENT_AUTH 在伺服器端加載用於客戶端證書驗證的  CA 證書。

但 SSLContext.load_default_certs() 加載系統的默認可信證書授權鏈,以便  客戶端  可以驗證  伺服器的證書。您通常不希望將這些用於客戶端證書。

在驗證證書部分,它提到您需要指定 CERT_REQUIRED:

在伺服器模式下,如果要使用SSL層對客戶端進行身份驗證(而不是使用更高級別的身份驗證機制),則還必須指定 CERT_REQUIRED 並同樣檢查客戶端證書。

我沒有發現如何 CERT_REQUIRED 在 SSLContext 構造函數或  wrap_socket() 方法中指定。事實證明,您必須 SSLContext 在伺服器上手動設置屬性以啟用客戶端證書驗證,如下所示:

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile = server_cert,keyfile = server_key)
context.load_verify_locations(憑證檔案錯誤= client_certs)

以下是驗證對方證書的客戶端和伺服器的完整示例:

在這個例子中,我們將創建自籤名伺服器和客戶端證書。通常情況下,您需要使用來自證書頒發機構(如 Let's Encrypt )的伺服器證書,並且將設置您自己的證書頒發機構,以便您可以籤署和吊銷客戶機證書。

創建伺服器證書:

openssl req -new -newkey rsa:2048-days 365 -nodes -x509 -keyout server.key -out server.crt

確保輸入 'example.com' 作為通用名稱。

接下來,生成一個客戶端證書:

openssl req -new -newkey rsa:2048-days 365 -nodes -x509 -keyout client.key -out client.crt

客戶端證書的通用名稱並不重要。

客戶代碼:

#!的/ usr / bin中/ python3

導入套接字
導入ssl

host_addr ='127.0.0.1'
host_port = 8082
server_sni_hostname ='example.com'
server_cert ='server.crt'
client_cert ='client.crt'
client_key ='client.key'

context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,cafile = server_cert)
context.load_cert_chain(certfile = client_cert,keyfile = client_key)

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
conn = context.wrap_socket(s,server_side = False,server_hostname = server_sni_hostname)
conn.connect((host_addr,host_port))
print(「SSL established。Peer:{}」。format(conn.getpeercert()))
列印(「發送:'你好,世界!')
conn.send(b「Hello,world!」)
列印(「關閉連接」)
conn.close()

伺服器代碼:

#!的/ usr / bin中/ python3

導入套接字
從套接字導入AF_INET,SOCK_STREAM,SO_REUSEADDR,SOL_SOCKET,SHUT_RDWR
導入ssl

listen_addr ='127.0.0.1'
listen_port = 8082
server_cert ='server.crt'
server_key ='server.key'
client_certs ='client.crt'

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile = server_cert,keyfile = server_key)
context.load_verify_locations(憑證檔案錯誤= client_certs)

bindsocket = socket.socket()
bindsocket.bind((listen_addr,listen_port))
bindsocket.listen(5)

而真:
   列印(「等待客戶」)
   newsocket,fromaddr = bindsocket.accept()
   print(「客戶端連接:{}:{}」。format(fromaddr [0],fromaddr [1]))
   conn = context.wrap_socket(newsocket,server_side = True)
   print(「SSL established。Peer:{}」。format(conn.getpeercert()))
   buf = b''#緩衝區保存接收到的客戶端數據
   嘗試:
       而真:
           data = conn.recv(4096)
           如果數據:
               #客戶向我們發送了數據。追加到緩衝區
               buf + =數據
           其他:
               #沒有更多的客戶數據。顯示緩衝區並關閉連接。
               print(「Received:」,buf)
               打破
   最後:
       列印(「關閉連接」)
       conn.shutdown(socket.SHUT_RDWR)
       conn.close()

伺服器的輸出如下所示:

$ python3 ./server.py
等待客戶
已連接客戶端:127.0.0.1:51372
建立SSL。Peer:{'subject':((('countryName','AU'),),
(('stateOrProvinceName','Some-State'),),(('organizationName','Internet
Widgits Pty Ltd'),),(('commonName','someclient'),)),'issuer':
((''countryName','AU'),),(('stateOrProvinceName','Some-State'),),
(('organizationName','Internet Widgits Pty Ltd'),),(('commonName',
'someclient'),)),'notBefore':'Jun 1 08:05:39 2018 GMT','version':3,
'serialNumber':'A564F9767931F3BC','notAfter':'Jun 1 08:05:39 2019 GMT'}
收到:b'Hello,世界!'
關閉連接
等待客戶

客戶輸出:

$ python3 ./client.py
建立SSL。Peer:{'notBefore':'May 30 20:47:38 2018 GMT','notAfter':
'May 30 20:47:38 2019 GMT','subject':((('countryName','NL'),),
(('stateOrProvinceName','GLD'),),(('localityName','Ede'),),
(('organizationName','Electricmonk'),),(('commonName','example.com'),)),
'(發行人):((('countryName','NL'),),(('stateOrProvinceName','GLD'),),
(('localityName','Ede'),),(('organizationName','Electricmonk'),),
(('commonName','example.com'),)),'version':3,'serialNumber':
'CAEC89334941FD9F'}
發送:'你好,世界!
關閉連接

一些注意事項:

您可以將多個客戶端證書連接成一個 PEM 文件,以驗證不同的客戶端。

您可以在伺服器和客戶端上重複使用相同的證書和密鑰。這樣,您不需要生成特定的客戶端證書。但是,使用該證書的任何客戶端都需要密鑰,並且能夠模擬伺服器。再也無法區分客戶。

您不需要設置您自己的證書頒發機構並籤署客戶端證書。您可以使用上述 openssl 命令生成它們,並將它們添加到受信任的證書文件中。如果您不再信任客戶端,只需從文件中刪除證書即可。

我不確定伺服器是否驗證客戶端證書的到期日期。

相關焦點

  • SSL_TLS 攻擊原理解析
    3、驗證公鑰證書4、交換會話秘鑰5、ssl連接建立完成,使用加密傳輸3、客戶端收到公鑰之後,利用自己的信任的根證書對收到的公鑰進行驗證.若通過,客戶端隨機生成對稱密鑰 (Pre-Master secret),通過伺服器發給客戶端,然後使用公鑰對對稱密鑰進行加密,並計算連接中全部報文信息的 hash ,再利用生成的對稱密鑰對 hash 值加密,然後把公鑰加密的對稱密鑰及對稱密鑰加密的 hash 值發送給伺服器
  • 如何在 CentOS 7 中使用 SSL/TLS 加固 FTP 伺服器進行安全文件傳輸
    Country Name (2 letter code) [XX]:INState or Province Name (full name) []:Lower ParelLocality Name (eg, city) [Default City]:MumbaiOrganization Name (eg, company) [Default
  • 在 Ubuntu 上使用 SSL/TLS 搭建一個安全的 FTP 伺服器
    要求在我們進行下一步之前,確保本文中的所有命令都將以root身份或者 sudo 特權帳號[3]運行。SSL/TLS3、在我們進行 vsftpd 配置之前,對於那些已啟用 UFW 防火牆[4]的用戶,你們必須打開埠 990 和 40000 - 50000,來在 vsftpd 配置文件中分別啟用 TLS 連接埠和被動埠的埠範圍:$ sudo ufw allow 990/tcp$ sudo ufw allow 40000:50000/tcp
  • TLS/SSL 高級進階
    因為每個證書並不是都被信任,所以客戶端首先就要了解一下,你這個證書能否用來進行驗證。如果不行的話,那麼你這次連接就是不被信任的,就沒有綠色的小鎖。這就需要了解一下,客戶端的驗證過程。CA 鏈式驗證首先,什麼叫做可信的證書呢?我們先要明白一個道理,HTTPS 是先建立在人與人之間的相互信任上,然後才建立在機器與機器的相互信任上。
  • Python 獲取 NCBI 基因名 SSL 證書異常?
    /SoftWare/Python-3.7.3/lib/python3.7/ssl.py", line 853, in _create    self.do_handshake()  File "/Bioinfo/Pipeline/SoftWare/Python-3.7.3/lib/python3.7/ssl.py", line 1117, in do_handshake
  • 使用ssl_exporter監控K8S集群證書
    使用kubeadm搭建的集群默認證書有效期是1年,續費證書其實是一件很快的事情。但是就怕出事了才發現,畢竟作為專業搬磚工程師,每天都很忙的。鑑於此,監控集群證書有效期是一件不得不做的事情。由於我的Prometheus是通過Prometheus Operator部署的,所以通過additional的方式進行抓取。
  • CentOS7下vsftpd over SSL/TLS加密傳輸配置實踐
    ]# lltotal 12lrwxrwxrwx. 1 root root   49 Jan  4  2020 ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pemlrwxrwxrwx. 1 root root   55 Jan  4  2020 ca-bundle.trust.crt ->
  • Let's Encrypt 免費通配符 SSL 證書申請教程
    要使用 ACME v2 協議申請通配符證書,只需一個支持該協議的客戶端就可以了,官方推薦的客戶端是 Certbot。更詳細的安裝可參考官方文檔:https://certbot.eff.org/申請通配符證書客戶在申請 Let’s Encrypt 證書的時候,需要校驗域名的所有權,證明操作者有權利為該域名申請證書,目前支持三種驗證方式:dns-01:給域名添加一個 DNS TXT 記錄。
  • 基於SSL的Client模型
    TLS與SSL在傳輸層與應用層之間對網絡連接進行加密。這裡不用糾結於SSL與TLS的區別,SSL V1.2版本及其往後都稱為TLS。常見的https協議就是由HTTP+SSL協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。
  • Https超文本傳輸協議-SSL證書
    HTTPS使用的主要目的是提供對網站伺服器的身份認證,同時保護交換數據的隱私與完整性。HTTPS有三大特點:1、內容加密:採用混合加密技術,中間者無法直接查看明文內容;2、驗證身份:通過證書認證客戶端訪問的是自己的伺服器;3、保護數據完整性:防止傳輸的內容被中間人冒充或者篡改。所以https化的企業網站,可以保證數據傳輸過程中的安全與完整。
  • 加強 Nginx 的 SSL 安全
    SSLv2 包含所有密碼,在舊版本中定義SSL的標準,現在棄用MD5 包含所有的密碼,使用過時的消息摘要5作為散列算法其它的設置確保你已經添加了以下幾行:1ssl_prefer_server_ciphers on;2ssl_session_cache shared:SSL:10m;在SSLv3或這是TLSv1握手時選擇一個密碼,通常是使用客戶端的偏好
  • 個人及中小企業SSL/TLS證書選購指南
    SSL 協議由網景公司開發,後來被 IETF 標準化,正式名稱叫作TLS,目前應用最廣泛的應該還是TLS 1.2,但一些網站已經開始使用TLS 1.3。SSL/TLS 可以認為是同一個協議,不過版本不相同。SSL/TLS的作用在於對數據傳輸進行加密,防止數據被監聽或篡改,避免釣魚網站,與網站訪問者建立信任,提升搜尋引擎排名等。
  • SSLScan:SSL版本檢測與密碼套件
    項目主頁https://github.com/rbsec/sslscan簡介sslscan是一個高效的c程序,它允許你檢測
  • 最近很火的免費SSL 使用教程
    ,消除了購買、安裝證書的複雜性,只需幾行命令,就可以完成證書的生成並投入使用,甚至十幾分鐘就可以讓自己的http站點華麗轉變成Https站點。Nginx虛擬主機的設置接下來進行配置Nginx虛擬主機文件,完整配置如下:server{listen 443 ssl;   //如果需要spdy也可以加上,lnmp1.2及其後版本都默認支持spdy,lnmp1.3 nginx 1.9.5以上版本默認支持http2server_name www.vpser.net;     //這裡是你的域名
  • DotNet SSL TLS證書問題分析排障
    123456789時間:2020-03-23 14:55:30 執行開始。。。我們可以通過這個工具的Site Scanner,輸入對應URL,然後Scan,這時候會打開ssllabs,進行網站證書檢測,我們可以拉到最後面,有一個Cipher Suites就可以看到對應的TLS 1.2加密套件支持。
  • 如何使用OpenSSL創建自籤名SSL證書
    相當一部分SSL證書需要付費購買,雖然一般不是很貴,成本也需要稍稍考慮一下。免費的SSL證書也有不少地方可以申請,但是能支持內網IP位址的好像沒有。基於這兩條考慮,考慮使用開源組件OpenSSL創建自籤名SSL證書。自己發給自己的證書,可不就想怎麼改就怎麼改。
  • 使用 Let's Encrypt 生成免費的 SSL 證書
    Let's Encrypt 是由網際網路安全研究小組(ISRG,一個公益組織)於 2015 年末推出的數字證書認證機構,將通過旨在消除當前手動創建和安裝證書的複雜過程的自動化流程,為安全網站提供免費的 SSL/TLS 證書。Let's Encrypt 的使用相對簡單,並且完全免費,是很多中小網站的首先。certbot 是什麼?
  • 基於RT-Thread 使用 wireshark 抓取 HTTPS 數據包
    簡單介紹TLS1.2握手和協商過程client hello客戶端向伺服器發送 tls 版本,加密方式,客戶端隨機數等。server hello伺服器端返回協商信息的結果,包括使用的 tls 版本,使用哪一種加密方式(cipher suite), 伺服器的隨機數(random_s)。
  • 物聯網網關 QT5 使用 SSL自籤名證書訪問雲端HTTPS REST API 服務
    在計算機網絡上,HTTPS經由超文本傳輸協議進行通信,但利用SSL/TLS來加密數據包。HTTPS的主要思想是在不安全的網絡上創建一安全信道,並可在使用適當的加密包和伺服器證書可被驗證且可被信任時,對竊聽和中間人攻擊提供合理的防護。HTTPS利用SSL/TLS來加密數據包,TLS協議是與應用層協議獨立無關的。
  • 申請免費的SSL證書
    申請免費的SSL證書此段時間通過沃通申請了免費的SSL證書, 這兩天發現Chrome提示證書不安全, Chrome已經對沃通證書不認證了.我們通過https://www.sslforfree.com/來申請免費的SSL的證書, 並且各大瀏覽器都認證.打開網站sslforfree網址: https://www.sslforfree.com/輸入自己的域名, 點擊Create Free SSL Certificate認證域名