PEP 247 – 加密哈希函数 API
- 作者:
- A.M. Kuchling <amk at amk.ca>
- 状态:
- 最终版
- 类型:
- 信息性
- 创建日期:
- 2001 年 3 月 23 日
- 发布历史:
- 2001 年 9 月 20 日
摘要
目前有多种不同的模块实现了 MD5 或 SHA 等加密哈希算法。本文档规定了此类算法的标准 API,以便于在不同实现之间进行切换。
规范
所有哈希模块都应提供相同的接口。可以添加额外的方法或变量,但本文档中描述的那些应始终存在。
哈希函数模块定义一个函数
new([string]) (无密钥哈希)new([key] , [string]) (有密钥哈希)创建一个新的哈希对象并返回它。第一种形式用于无密钥哈希,例如 MD5 或 SHA。对于 HMAC 等有密钥哈希,key 是一个必需参数,包含一个用于密钥的字符串。在这两种情况下,如果提供了可选的 string 参数,它将立即哈希到对象的初始状态中,就像调用了obj.update(string)一样。创建哈希对象后,可以使用其
update()方法将任意字符串馈入对象,并且可以随时通过调用对象的digest()方法获取哈希值。可以向此函数添加任意额外的关键字参数,但如果未提供,则应使用合理的默认值。例如,对于支持可变轮数和多种不同输出大小的哈希函数,可以添加
rounds和digest_size关键字,它们应默认为被认为是安全的值。
哈希函数模块定义一个变量
digest_size一个整数值;由该模块创建的哈希对象产生的摘要大小,以字节为单位。您也可以通过创建一个示例对象并访问其digest_size属性来获取此值,但从模块中获取此值可能很方便。输出大小可变的哈希将此变量设置为None。
哈希对象需要一个属性
digest_size此属性与模块级别的digest_size变量相同,衡量哈希对象产生的摘要大小,以字节为单位。如果哈希具有可变输出大小,则必须在创建哈希对象时选择此输出大小,并且此属性必须包含所选大小。因此,None不是此属性的合法值。
哈希对象需要以下方法
copy()返回此哈希对象的独立副本。此副本的更新不会影响原始对象。
digest()以包含 8 位数据的字符串形式返回此哈希对象的哈希值。此函数不会以任何方式更改对象;调用此函数后,您可以继续更新对象。
hexdigest()以包含十六进制数字的字符串形式返回此哈希对象的哈希值。数字a到f应使用小写字母。与.digest()方法一样,此方法不得更改对象。
update(string)将 string 哈希到哈希对象的当前状态中。update()可以在哈希对象的生命周期内被调用任意次。
哈希模块可以定义额外的模块级函数或对象方法,并且仍然符合此规范。
下面是一个示例,使用名为 MD5 的模块
>>> from Crypto.Hash import MD5
>>> m = MD5.new()
>>> m.digest_size
16
>>> m.update('abc')
>>> m.digest()
'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'
>>> m.hexdigest()
'900150983cd24fb0d6963f7d28e17f72'
>>> MD5.new('abc').digest()
'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'
基本原理
摘要大小以字节为单位,而不是位,尽管哈希算法大小通常以位为单位引用;例如,MD5 是一个 128 位算法,而不是 16 字节算法。这是因为在我查看的示例代码中,经常需要以字节为单位的长度(在文件中向前或向后查找;计算输出字符串的长度),而很少使用以位为单位的长度。因此,需要以位为单位的大小的少数人将不得不承担将 digest_size 乘以 8 的负担。
有人建议将 update() 方法更好地命名为 append()。但是,该方法确实导致哈希对象的当前状态被更新,并且 Python 附带的 md5 和 sha 模块已经使用了 update(),因此最简单的做法是保持名称 update() 不变。
有密钥哈希构造函数参数的顺序是一个棘手的问题。不清楚 key 应该排在第一位还是第二位。它是一个必需参数,通常的约定是将必需参数放在前面,但这也意味着 string 参数从第一个位置移动到第二个位置。可能会混淆并将单个参数传递给有密钥哈希,认为您正在将初始字符串传递给无密钥哈希,但为了避免这种潜在错误,似乎不值得使有密钥哈希的接口更模糊。
更改
2001-09-17:将 clear() 重命名为 reset();向对象添加了 digest_size 属性;添加了 .hexdigest() 方法。
2001-09-20:完全删除了 reset() 方法。
2001-09-28:对于可变大小哈希,将 digest_size 设置为 None。
致谢
感谢 Aahz、Andrew Archibald、Rich Salz、Itamar Shtull-Trauring 以及 python-crypto 列表的读者对本 PEP 的评论。
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0247.rst