1 回答
TA贡献1853条经验 获得超6个赞
在 PHP 代码中(更准确地说是openssl_encrypt
),明确指定了 AES 变体,例如当前情况下的aes-128-...
,即 PHP 使用 AES-128。太长的键会被截断,太短的键会用0
值填充。由于hash
PHP 代码中的方法以十六进制字符串形式返回其结果,因此 16 字节 MD5 哈希值由 32 个字符(32 字节)表示,即在当前情况下 PHP 使用密钥的前 16 个字节 (AES-128)。
Python 代码中的方法hexdigest
也以十六进制字符串形式返回结果。然而,在Python代码中(更准确地说是PyCryptodome),AES变体由密钥大小指定,即Python代码使用完整的32字节密钥,因此使用AES-256。
不同的密钥和 AES 变体是导致不同结果的主要原因。要解决此问题,两个代码中必须使用相同的密钥和 AES 变体:
选项 1 是在 Python 代码中也使用 AES-128。这可以通过以下更改来实现:
obj = AES.new(ENC_KEY[:16].encode("utf8"), AES.MODE_CFB, IV.encode("utf8"))
然后输出
b0016a55
是按照 PHP 代码的结果aes-128-cfb8
。选项 2 是在 PHP 代码中也使用 AES-256。
aes-128...
这可以通过替换来完成aes-256...
然后输出是aes-256-cfb8-1: 117c1974 aes-256-cfb1-1: 54096db1 aes-256-cfb-1 : 11bfdaa9
正如预期的那样, 的输出117c1974
与aes-128-cfb8
Python 代码的原始值相匹配。
CFB 模式将分组密码更改为流密码。从而n
在每个加密步骤中对位进行加密,这称为CFBn
。
PHP 中也使用术语CFBn
(或),即表示 1 位、8 位(= 1 字节)和整个块(16 字节)的加密。在 Python 中,每步的位数用 指定。cfbn
CFB1
CFB8
CFB
segment_size
...-cfb8
即PHP 中的对应项是 Python 中, PHP 中segment_size = 8
的对应项是Python 中。...-cfb
segment_size = 128
下面假设两个代码中使用相同的密钥和相同的 AES 变体。
由于是默认值,Python 代码的结果与 PHP 代码的segment_size = 8
结果相同。...-cfb8
如果选择在 Python 代码中,则结果与在 PHP 代码中segement_size = 128
相同。...-cfb
但是,在 PyCryptodome 中,该值segment_size
必须是 8 的整数倍,否则错误消息“segment_size”必须为正数并显示8 位的倍数。因此,CFB1
PyCryptodome 不支持该模式。
另请注意:
摘要的结果也可以在两种代码中以二进制形式返回,而不是以十六进制字符串形式返回。为此,
hash
必须将 PHP 方法的第三个参数设置为TRUE
(默认值FALSE
:)。在Python中,只需使用digest
方法而不是hexdigest
.在 PHP 代码中,对于像 CFB 这样的流密码模式,填充会自动禁用,因此标志
OPENSSL_ZERO_PADDING
(可用于显式禁用填充)没有任何区别。utf8_encode
允许您从 ISO-8859-1 编码转换为 UTF-8,但由于它$ENC_KEY
由字母数字字符(十六进制编码)组成,因此没有任何效果。但是,一般来说,任意二进制数据(例如摘要的结果)不得采用 UTF8 编码,因为这会损坏数据。还有其他用于此目的的编码,例如 Base64。如果摘要的结果以二进制形式返回(参见第一点),则不能执行 UTF8 编码。在 CFB 模式的上下文中,旧版 PyCrypto 库中存在一个错误,该错误要求明文的长度是段大小的整数倍。否则会出现以下错误:输入字符串的长度必须是段大小 16 的倍数。
- 1 回答
- 0 关注
- 184 浏览
添加回答
举报