Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 452 – 密码哈希函数 API v2.0

作者:
A.M. Kuchling <amk at amk.ca>, Christian Heimes <christian at python.org>
状态:
最终版
类型:
信息性
创建日期:
2013年8月15日
发布历史:

取代:
247

目录

摘要

有几个不同的模块可用于实现MD5或SHA等加密哈希算法。本文档为这些算法指定了一个标准API,以方便在不同实现之间切换。

规范

所有哈希模块都应该提供相同的接口。可以添加额外的方法或变量,但本文档中描述的那些应该始终存在。

哈希函数模块定义一个函数

new([string])            (无密钥哈希)

new(key, [string], [digestmod])    (有密钥哈希)
创建一个新的哈希对象并返回它。第一种形式用于无密钥哈希,例如MD5或SHA。对于HMAC等有密钥哈希,'key'是一个必需参数,包含一个表示要使用的密钥的字符串。在两种情况下,如果提供了可选的'string'参数,它将立即被哈希到对象的起始状态,就像调用了obj.update(string)一样。

创建哈希对象后,可以使用其update()方法将任意字节数据输入到对象中,并且可以随时通过调用对象的digest()方法获取哈希值。

尽管参数名为“string”,但哈希对象仅对8位数据进行操作。“key”和“string”都必须是字节类对象(bytes、bytearray…)。哈希对象也可以支持一维、连续的缓冲区作为参数。文本(unicode)在Python 3.x中不再支持。Python 2.x实现可以接受仅包含ASCII的unicode作为参数,但可移植代码不应依赖此功能。

可以向此函数添加任意额外的关键字参数,但如果未提供,则应使用合理的默认值。例如,可以为支持可变轮数和多种不同输出大小的哈希函数添加“rounds”和“digest_size”关键字,它们应默认为被认为是安全的值。

哈希函数模块定义一个变量

digest_size
一个整数值;由该模块创建的哈希对象生成的摘要大小,以字节为单位。您也可以通过创建一个示例对象并访问其“digest_size”属性来获取此值,但将此值从模块中直接获取可能更方便。具有可变输出大小的哈希将此变量设置为None。

哈希对象需要以下属性

digest_size
此属性与模块级别的digest_size变量相同,表示由哈希对象生成的摘要大小,以字节为单位。如果哈希具有可变输出大小,则必须在创建哈希对象时选择此输出大小,并且此属性必须包含所选的大小。因此,None 不是此属性的合法值。
block_size
一个整数值或NotImplemented;哈希算法的内部块大小,以字节为单位。块大小由HMAC模块用于将密钥填充到digest_size,或者如果密钥长度超过digest_size,则对密钥进行哈希。如果哈希算法没有标准化的HMAC算法,则返回NotImplemented
名称
一个文本字符串值;哈希算法的规范的、小写名称。该名称应是hashlib.new的合适参数。

哈希对象需要以下方法

copy()
返回此哈希对象的独立副本。对此副本的更新不会影响原始对象。
digest()
将此哈希对象的哈希值作为包含8位数据的字节返回。此函数不会以任何方式更改对象;调用此函数后,您可以继续更新对象。
hexdigest()
将此哈希对象的哈希值作为包含十六进制数字的字符串返回。数字“a”到“f”应使用小写字母。与.digest()方法一样,此方法不得更改对象。
update(string)
将字节类“string”哈希到哈希对象的当前状态。update()可以在哈希对象的生命周期内被调用任意次。

哈希模块可以定义额外的模块级函数或对象方法,并且仍然符合本规范。

这是一个示例,使用名为“MD5”的模块

>>> import hashlib
>>> from Crypto.Hash import MD5
>>> m = MD5.new()
>>> isinstance(m, hashlib.CryptoHash)
True
>>> m.name
'md5'
>>> m.digest_size
16
>>> m.block_size
64
>>> m.update(b'abc')
>>> m.digest()
b'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'
>>> m.hexdigest()
'900150983cd24fb0d6963f7d28e17f72'
>>> MD5.new(b'abc').digest()
b'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'

基本原理

摘要大小以字节而不是位为单位,即使哈希算法大小通常以位为单位;例如,MD5是一个128位算法,而不是16字节算法。这是因为在我查看的示例代码中,经常需要以字节为单位的长度(用于在文件中向前或向后查找;计算输出字符串的长度),而以位为单位的长度很少使用。因此,实际需要以位为单位的大小的少数人将不得不将digest_size乘以8。

有人建议将update()方法更好地命名为append()。然而,该方法确实导致哈希对象的当前状态被更新,并且Python中包含的md5和sha模块已经使用了update(),因此最简单的做法似乎是保留名称update()

有密钥哈希的构造函数参数顺序是一个棘手的问题。不清楚密钥应该放在第一位还是第二位。它是一个必需参数,通常的惯例是将必需参数放在前面,但这也意味着“string”参数从第一个位置移动到第二个位置。可能会混淆并将单个参数传递给有密钥哈希,认为您正在将初始字符串传递给无密钥哈希,但为了避免这种潜在错误,使有密钥哈希的接口更不清楚似乎不值得。

从1.0版到2.0版的更改

密码哈希函数API的2.0版澄清了API的某些方面并使其保持最新。它还正式化了已经成为事实标准并由大多数实现提供的方面。

2.0版引入了以下新属性

名称
name属性由问题18532强制要求。
block_size
新版本还规定,返回值NotImplemented会阻止HMAC支持。

2.0版考虑了Python 3.0中二进制数据和文本数据的分离。new()update()的“string”参数以及“key”参数都必须是字节类对象。在Python 2.x上,哈希对象也可以支持仅包含ASCII的unicode。参数的实际名称没有改变,因为它是公共API的一部分。代码可能依赖于参数名为“string”这一事实。

更改

  • 2001-09-17: 将clear()重命名为reset();向对象添加digest_size属性;添加.hexdigest()方法。
  • 2001-09-20: 完全删除reset()方法。
  • 2001-09-28: 对于可变大小哈希,将digest_size设置为None
  • 2013-08-15: 添加block_sizename属性;澄清“string”实际上指的是字节类对象。

致谢

感谢Aahz、Andrew Archibald、Rich Salz、Itamar Shtull-Trauring以及python-crypto列表的读者对本PEP的评论。


来源:https://github.com/python/peps/blob/main/peps/pep-0452.rst

最后修改:2025-02-01 08:59:27 GMT