AES Python加密和Ruby加密 – 不同的行为?

从这个网站我有这个代码片段:

>>> from Crypto.Cipher import AES >>> obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456') >>> message = "The answer is no" >>> ciphertext = obj.encrypt(message) >>> list(bytearray(ciphertext)) [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241] 

当我接受这个数组并将其转换为Ruby中的String并继续解密时,会发生错误:

 >> require 'openssl' => true >> obj2 = OpenSSL::Cipher::Cipher.new("AES-128-CBC") => # >> obj2.decrypt => # >> obj2.key = 'This is a key123' => "This is a key123" >> obj2.iv = 'This is an IV456' => "This is an IV456" >> ciphertext = [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241].pack('c*') => "\xD6\x83\x8Dd!VT\x92\xAA`A\x05\xE0\x9B\x8B\xF1" >> obj2.update(ciphertext) + obj2.final OpenSSL::Cipher::CipherError: bad decrypt from (irb):20:in `final' from (irb):20 from /home/danyel/.rbenv/versions/2.0.0-p0/bin/irb:12:in `' 

为什么这不起作用?

这是可以理解的混淆 – PyCrypto在这里有点偏离轨道并且与通常的实现相违背。 如果您对加密数据通常看起来很熟悉,那么Python输出看起来很明显错误,并为您提供了一个起点。 如果你不是,很容易想知道到底出了什么问题并且不知道从哪里开始寻找。

在“正常”实现中,默认情况下将使用填充,并且最终(在这种情况下)将使用16字节更长的加密输出。

例如,使用Ruby加密,结果如下:

 >> ciphertext => "\xD6\x83\x8Dd!VT\x92\xAA`A\x05\xE0\x9B\x8B\xF1\xD5f\xC7\xFFNI\xC7N\xBC-;!\f\xF1!\xB4" >> ciphertext.bytes => [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241, 213, 102, 199, 255, 78, 73, 199, 78, 188, 45, 59, 33, 12, 241, 33, 180] 

由于我无法立即找到的原因,PyCrypto选择仅使用未填充数据 。 与PyCrypto交换数据时,您需要适当地配置任何其他库。

对于Ruby的OpenSSL库, Cipher对象公开了一个padding属性,可用于禁用填充:

 >> require 'openssl' => true >> obj2 = OpenSSL::Cipher::Cipher.new("AES-128-CBC") => # >> obj2.decrypt => # >> obj2.key = 'This is a key123' => "This is a key123" >> obj2.iv = 'This is an IV456' => "This is an IV456" >> obj2.padding = 0 => 0 >> ciphertext = [214, 131, 141, 100, 33, 86, 84, 146, 170, 96, 65, 5, 224, 155, 139, 241].pack('c*') => "\xD6\x83\x8Dd!VT\x92\xAA`A\x05\xE0\x9B\x8B\xF1" >> obj2.update(ciphertext) + obj2.final => "The answer is no"