Python 32 网络编程 HMAC模块和其他补充

Python 32 网络编程 HMAC模块和其他补充

旧博客Python系列

send与sendall

官方文档对socket模块下的socket.send()和socket.sendall()解释如下:
socket.send(string[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data.
send()的返回值是发送的字节数量,这个数量值可能小于要发送的string的字节数,也就是说可能无法发送string中所有的数据。如果有错误则会抛出异常。

socket.sendall(string[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent.
尝试发送string的所有数据,成功则返回None,失败则抛出异常。
故,下面两段代码是等价的:

#sock.sendall('Hello world\n')

#buffer = 'Hello world\n'
#while buffer:
#    bytes = sock.send(buffer)
#    buffer = buffer[bytes:]

hmac模块验证用户身份

在之前学习hashlib的时候知道,不能明文存储用户的密码.所以我们有两个方案,一是存储加过盐的用户名和密码,二是用一个直接用一段密钥或者文件都可以,当做验证工具.

Python里有一个用于用户身份验证的模块,叫做HMAC (Keyed-Hashing for Message Authentication):

HMAC是一种消息摘要算法,是一种特殊的MAC(消息认证码),内部使用别的摘要算法进行摘要的计算(比如MD5)。相比MAC,HMAC在生成摘要的时候加入了密钥,这使得HMAC码不仅可以用于验证消息完整性,并且保证了其无法被伪造。注意,摘要算法跟加密算法是有区别的。

查看源码可以知道,hmac模块中最核心的就是HMAC类,可以直接通过实例化来获取该类的实例,也可以通过调用函数hmac.new(key, msg=None, digestmod=None)获取.

参数key可以是一个bytes对象或者bytearray对象,是用于加密的密钥。如果key大于Block Size(默认是64),会先计算一次消息摘要,小于的话用0填充到与Block Size相同的长度。

参数msg是用于加密的消息。

参数digestmod是用于计算摘要的算法,默认使用hashlib.md5。这个参数支持三种类型的值:

可以是hashlib里面的其他的构造器,比如hashlib.sha1、hashlib.sha256等
可以是一个字符串,会调用hashlib.new(digestmod)获取相应的构造器
可以是一个符合PEP247标准的模块,这时会调用digestmod.new()
hmac.compare_digest(a, b)

在hmac模块中,通过from _operator import _compare_digest as compare_digest引入了这个函数。这个函数简单点来说就是用来比较a与b值是否相等的,当将外部输入的值与HMAC.degest()/HMAC.hexdigest()的输出做比较时,有可能会遭到时序攻击,所以可以通过调用这个函数比较值并防御可能存在的攻击行为。Python3.3版本后新增。

HMAC的很多使用方法与hashlib有些类似,只不过加了一个key,在加上msg来生成hash,然后进行比较即可.

一般可以提前将密钥告知需要认证的用户,然后发送本地的一个随机字符串作为消息给用户端,用户端拿到该随机字符串后也用hmac进行计算,将结果返回服务端,服务端用compare_digest方法进行比较,如果相同,则说明对方持有密钥,认证通过.

import hmac

a = hmac.HMAC(b'ffff', 'jenny'.encode('utf-8'))

b = a.hexdigest()
print(b)  # 768c7db73485842cd600c30fbd2dc8f4

c = hmac.HMAC(b'ffff', 'jenny'.encode('utf-8'))

d = c.hexdigest()
print(d)  # 768c7db73485842cd600c30fbd2dc8f4

e = hmac.compare_digest(b, d)
print(e)  # True

可见用hmac模块可以很方便的加盐,而其内部其实也是导入了hashlib模块用来做验证,如果不指定哈希函数,则默认采用MD5算法.

hmac是一个比较简单的模块,官方文档:https://docs.python.org/3/library/hmac.html#module-hmac

从FTP的作业来看,面对对象方面组织代码还是很有问题,这个只能通过刻意练习和多看代码来实现了.socketserver模块的写法,就是一个不算太好的参考,但是以类组织代码的形式值得学习.

LICENSED UNDER CC BY-NC-SA 4.0
Comment