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

Dan*_*yel 8 ruby python encryption aes

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

>>> 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]
Run Code Online (Sandbox Code Playgroud)

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

>> require 'openssl'
=> true
>> obj2 = OpenSSL::Cipher::Cipher.new("AES-128-CBC")
=> #<OpenSSL::Cipher::Cipher:0x007fa388389b30>
>> obj2.decrypt
=> #<OpenSSL::Cipher::Cipher:0x007fa388389b30>
>> 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 `<main>'
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?

col*_*inm 10

这是可以理解的混淆 - 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]
Run Code Online (Sandbox Code Playgroud)

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

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

>> require 'openssl'
=> true
>> obj2 = OpenSSL::Cipher::Cipher.new("AES-128-CBC")
=> #<OpenSSL::Cipher::Cipher:0x007fe62407a9b0>
>> obj2.decrypt
=> #<OpenSSL::Cipher::Cipher:0x007fe62407a9b0>
>> 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"
Run Code Online (Sandbox Code Playgroud)