Pycrypto AES 256的初始化向量大小

4

这里是案例,我有一个使用AES256,CBC的PHP脚本。密钥和IV长度都为32字节。

data= '123456789abcdef' 
from Crypto.Cipher import AES
a = AES.new('oqufXQ(?bc=6_hR2I3sMZChDpb6dDlw4',2,'fOaiIOkD8*9Xeu_s4_bb87Ox_UG+D9GA')
print a.encrypt(data)

而我遇到的错误
<type 'exceptions.ValueError'>: IV must be 16 bytes long
Traceback (most recent call last):
  File "/base/data/home/apps/s~xxxxxxx/1.155074369696961822/main.py", line 4, in <module>

可运行的PHP代码

 echo base64_encode(encrypt('0123456789abcdef'))  ;


 function encrypt($data)
  {
    return mcrypt_encrypt(MCRYPT_RIJNDAEL_256 ,'oqufXQ(?bc=6_hR2I3sMZChDpb6dDlw4', $data , MCRYPT_MODE_CBC, utf8_encode('fOaiIOkD8*9Xeu_s4_bb87Ox_UG+D9GA') );
  }

我无法更改IV大小。

请注意,我不是很熟悉Python,只需要一种加密数据的方法,因为它将成为一个应用引擎。


4
IV的大小是无法更改的。AES 256是一个块密码,块大小为16个字节,因此在使用任何标准的密码模式(该模式使用IV)时,IV的大小为一个块,即16个字节。 - Steve Jessop
我的 PHP 脚本正在使用一个长度为 32 字节的随机字符串作为 IV,我做错了什么吗?mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_CBC)返回 32。 - user80287
抱歉,我不知道。我期望AES256在CBC模式下使用一个IV块,该块与第一个明文块进行XOR操作,然后再加密该明文。如果mcrypt执行的操作与此不同,并涉及另外16个字节的IV,则它没有使用我理解的CBC密码模式,这意味着它无法与按照我理解方式工作的实现进行互操作。我并不认为我的理解有多大问题,但它与您从pycrypto获取的错误消息相匹配,因此我认为密码模式在某种程度上没有匹配。 - Steve Jessop
哦,我想要检查的一件事情是mcrypt是否使用pbkdf2或其他方法来操作你给它的所谓IV,并将其部分结果用作真正的IV。 - Steve Jessop
添加了能够正常加密的 PHP 代码,但我不认为它使用 PBKDF2 来派生新的 IV,不确定 PHP 是否默认使用该算法。 - user80287
1个回答

11

Aha!

对于"256"的具体含义有不同的看法。

AES 的块大小固定为128位,因此"AES 256"表示128比特块、256比特密钥、14轮。然而,Rijndael允许密钥大小和块大小都可以变化。MCRYPT_RIJNDAEL_256指的是Rijndael中块大小设置为256(我不知道有多少轮)。因此,它确实需要一个32字节的IV。您的PHP脚本没有使用AES 256。

这在https://bugs.php.net/bug.php?id=47125中得到了证实——报告者认为这是PHP mcrypt的错误,PHP认为这是libmcrypt的错误,但这并不是一个错误,因为libmcrypt确实记录了MCRYPT_RIJNDAEL_256的含义(至少是Linux上的mcrypt手册记录的,我的谷歌搜索没有找到任何实际的libmcrypt文档)。不幸的是,它所表示的东西与AES 256的含义不同。

因此,您正使用相互关联但几乎完全不同的密码进行加密和解密。

不好的消息是,在PyCrypto中似乎没有Crypto.Cipher.RIJNDAEL。如果您可以在PHP脚本中向MCRYPT_RIJNDAEL_128传递256位密钥,那么就是AES 256(感谢Paŭlo)。


@user80287。AES 128、192和256是配置Rijndael的三种特定方式。但是,Rijndael比这些方式有更多的配置选项。因此,如果您拥有完整的Rijndael实现,则可以轻松地执行AES,但实现者不一定会编写完全灵活的Rijndael,他们可能只削减所需的位数。因此,AES实现不一定支持除128以外的块大小。 - Steve Jessop
哇!感谢您的解释。我原本认为 AES 和 Rijndael 具有相同的实现方式,但是我无法控制密钥或 IV,也就是说我无法更改 IV。所以我需要使用其他库,再次感谢。 - user80287
2
@user80287,Steve:实际上,MCRYPT_RIJNDAEL_128(“具有128位块大小的Rijndael”)是AES的所有三个版本 - 只需传递正确大小的密钥,它将选择正确的算法(AES-128,AES-192,AES-256)。 (如果您无法更改PHP脚本,则无法帮助您。) - Paŭlo Ebermann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接