11.9 简�的客户端认�¶

问题¶

你想在分布�系统中实现一个简�的客户端连接认�功能,��想�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, AF_INET, 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中有详细介�。