Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 增强提案

PEP 272 – 块加密算法 API v1.0

作者:
A.M. Kuchling <amk at amk.ca>
状态:
最终
类型:
信息性
创建:
2001年9月18日
修订历史:
2002年4月17日,2002年5月29日

目录

摘要

本文档指定了用于秘密密钥块加密算法(如 DES 或 Rijndael)的标准 API,从而更轻松地在不同算法和实现之间切换。

引言

加密算法以某种依赖于可变密钥的方式转换其输入数据(称为明文),生成密文。如果且仅当知道密钥时,转换才能轻松地反转。密钥是从某个非常大的可能密钥空间中选择的比特序列。加密算法有两类:块密码和流密码。

块密码加密固定大小的多字节输入(通常为 8 或 16 字节长),并且可以在各种反馈模式下运行。此规范中支持的反馈模式为

编号 常量 描述
1 MODE_ECB 电子密码本
2 MODE_CBC 密码块链接
3 MODE_CFB 密码反馈
5 MODE_OFB 输出反馈
6 MODE_CTR 计数器

这些模式应按照 NIST 出版物 SP 800-38A [1] 中的描述进行实现。前三种反馈模式的描述也可以在布鲁斯·施奈尔(Bruce Schneier)的书籍《应用密码学》[2] 中找到。

(数值 4 保留给 MODE_PGP,这是 RFC 2440:“OpenPGP 消息格式”中描述的 CFB 的变体。这种模式被认为不那么重要,因此不值得要求所有块加密密码都支持它,尽管支持它是一个不错的额外功能。)

从严格的形式意义上讲,流密码逐位加密数据;实际上,流密码以逐字符为基础工作。此 PEP 仅旨在为块密码指定接口,尽管流密码可以通过将“block_size”固定为 1 来支持此处描述的接口。反馈模式对流密码也没有意义,因此唯一合理的反馈模式将是 ECB 模式。

规范

加密模块可以在此 PEP 中描述的功能、方法和属性之外添加其他功能、方法和属性,但要声明模块符合此 PEP,则必须存在 PEP 中描述的所有功能。

秘密密钥加密模块应定义一个函数

new(key, mode, [IV], **kwargs)

返回一个加密对象,使用字符串“key”中包含的密钥,并使用反馈模式“mode”,该模式必须是上述表格中的一个常量。

如果“mode”为 MODE_CBC 或 MODE_CFB,则必须提供“IV”,并且它必须是与块大小相同的长度的字符串。不提供“IV”的值将导致引发ValueError异常。

根据算法的不同,模块可能支持此函数的其他关键字参数。此 PEP 指定了一些关键字参数,并且模块可以自由添加其他关键字参数。如果未为给定关键字提供值,则应使用安全默认值。例如,如果某个算法在 1 到 16 之间具有可选的轮数,并且 1 轮加密不安全,而 8 轮加密被认为是安全的,则“rounds”的默认值应为 8 或更大。(模块实现者也可以选择一个非常慢但安全的值,例如本例中的 16。此决定留给实现者。)

下表列出了此 PEP 定义的关键字参数

关键字 含义
counter 返回计数器块的可调用对象(请参见下文;仅限 CTR 模式)
rounds 要使用的加密轮数
segment_size 数据和密文段的大小,以位为单位(请参见下文;仅限 CFB 模式)

计数器反馈模式需要一系列输入块,称为计数器,用于生成输出。当“mode”为 MODE_CTR 时,必须提供“counter”关键字参数,并且其值必须是可调用对象,例如函数或方法。对该可调用对象的连续调用必须返回一系列长度为“block_size”且永不重复的字符串。(NIST 出版物的附录 B 提供了一种生成此类序列的方法,但这超出了本 PEP 的范围。)

CFB 模式对长度为“segment_size”位的明文和密文段进行操作。因此,在使用此模式时,输入和输出字符串的长度必须是“segment_size”位的倍数。“segment_size”必须是 1 到 block_size*8(含)之间的整数。(因子 8 来自“block_size”以字节为单位而不是以位为单位)。此参数的默认值应为 block_size*8。为了简单起见,实现者可以将“segment_size”限制为 8 的倍数,但为了通用性,鼓励他们支持任意值。

秘密密钥加密模块应定义两个变量

  • block_size

    整数值;此模块加密的块的大小,以字节为单位。对于所有反馈模式,传递给 encrypt() 和 decrypt() 的字符串的长度必须是块大小的倍数。

  • key_size

    整数值;此模块所需的密钥的大小,以字节为单位。如果 key_size 为 None,则算法接受可变长度密钥。这可能意味着模块接受任何随机长度的密钥,或者有几个不同的可能长度,例如 16、24 或 32 字节。您不能将长度为 0 的密钥(即空字符串“”)作为可变长度密钥传递。

密码对象应具有两个属性

  • block_size

    整数值,等于此对象加密的块的大小。对于块大小可变的算法,此值等于为此对象选择的块大小。

  • IV

    包含将用于启动密码反馈模式的初始值;它始终是一个正好一个块长度的字符串。加密或解密字符串后,此值将更新以反映修改后的反馈文本。它是只读的,不能分配新值。

密码对象需要以下方法

  • decrypt(string)

    解密“string”,使用对象中与密钥相关的数据以及适当的反馈模式。字符串的长度必须是算法块大小的精确倍数,或者在 CFB 模式下,是段大小的精确倍数。返回包含明文的字符串。

  • encrypt(string)

    加密非空字符串,使用对象中与密钥相关的数据以及适当的反馈模式。字符串的长度必须是算法块大小的精确倍数,或者在 CFB 模式下,是段大小的精确倍数。返回包含密文的字符串。

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

>>> import DES
>>> obj = DES.new('abcdefgh', DES.MODE_ECB)
>>> plaintext = "Guido van Rossum is a space alien."
>>> len(plaintext)
34
>>> obj.encrypt(plaintext)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
ValueError: Strings for DES must be a multiple of 8 in length
>>> ciphertext = obj.encrypt(plain+'XXXXXX')   # Add padding
>>> ciphertext
'\021,\343Nq\214DY\337T\342pA\372\255\311s\210\363,\300j\330\250\312\347\342I\3215w\03561\303dgb/\006'
>>> obj.decrypt(ciphertext)
'Guido van Rossum is a space alien.XXXXXX'

参考文献

更改

2002-04:删除了对流密码的引用;重新命名 PEP;在反馈模式常量前添加了MODE_;删除了 PGP 反馈模式;添加了 CTR 和 OFB 反馈模式;阐明了数字以字节为单位还是以位为单位。

2002-09:使用“可变长度密钥”代替“任意长度”阐明了密钥长度的讨论。

致谢

感谢 python-crypto 列表的读者对本 PEP 的评论。


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

上次修改时间:2023年9月9日 17:39:29 GMT