8

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

>>> 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 中的字符串并继续解密时,会发生错误:

>> 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>'

为什么这不起作用?

4

1 回答 1

11

这是可以理解的混乱——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")
=> #<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"
于 2013-10-29T16:25:53.550 回答