Python 實現簡單的客戶端認證
阿新 • • 發佈:2020-07-30
問題
你想在分散式系統中實現一個簡單的客戶端連線認證功能,又不想像SSL那樣的複雜。
解決方案
可以利用 hmac 模組實現一個連線握手,從而實現一個簡單而高效的認證過程。下面是程式碼示例:
import hmac import os def client_authenticate(connection,secret_key): ''' Authenticate client to a remote service. connection represents a network connection. secret_key is a key known only to both client/server. ''' message = connection.recv(32) hash = hmac.new(secret_key,message) digest = hash.digest() connection.send(digest) def server_authenticate(connection,secret_key): ''' Request client authentication. ''' message = os.urandom(32) connection.send(message) hash = hmac.new(secret_key,message) digest = hash.digest() response = connection.recv(len(digest)) return hmac.compare_digest(digest,response)
基本原理是當連線建立後,伺服器給客戶端傳送一個隨機的位元組訊息(這裡例子中使用了 os.urandom() 返回值)。 客戶端和伺服器同時利用hmac和一個只有雙方知道的金鑰來計算出一個加密雜湊值。然後客戶端將它計算出的摘要傳送給伺服器, 伺服器通過比較這個值和自己計算的是否一致來決定接受或拒絕連線。摘要的比較需要使用 hmac.compare_digest() 函式。 使用這個函式可以避免遭到時間分析攻擊,不要用簡單的比較操作符(==)。 為了使用這些函式,你需要將它整合到已有的網路或訊息程式碼中。例如,對於sockets,伺服器程式碼應該類似下面:
from socket import socket,AF_INET,SOCK_STREAM secret_key = b'peekaboo' def echo_handler(client_sock): if not server_authenticate(client_sock,secret_key): client_sock.close() return while True: msg = client_sock.recv(8192) if not msg: break client_sock.sendall(msg) def echo_server(address): s = socket(AF_INET,SOCK_STREAM) s.bind(address) s.listen(5) while True: c,a = s.accept() echo_handler(c) echo_server(('',18000)) Within a client,you would do this: from socket import socket,SOCK_STREAM secret_key = b'peekaboo' s = socket(AF_INET,SOCK_STREAM) s.connect(('localhost',18000)) client_authenticate(s,secret_key) s.send(b'Hello World') resp = s.recv(1024)
討論
hmac 認證的一個常見使用場景是內部訊息通訊系統和程序間通訊。 例如,如果你編寫的系統涉及到一個叢集中多個處理器之間的通訊, 你可以使用本節方案來確保只有被允許的程序之間才能彼此通訊。 事實上,基於 hmac 的認證被 multiprocessing 模組使用來實現子程序直接的通訊。
還有一點需要強調的是連線認證和加密是兩碼事。 認證成功之後的通訊訊息是以明文形式傳送的,任何人只要想監聽這個連線線路都能看到訊息(儘管雙方的金鑰不會被傳輸)。
hmac認證演算法基於雜湊函式如MD5和SHA-1,關於這個在IETF RFC 2104中有詳細介紹。
以上就是Python 實現簡單的客戶端認證的詳細內容,更多關於Python 客戶端認證的資料請關注我們其它相關文章!