为什么Ruby openssl aes 128 cbc的前16个字节错误?

时间:2013-05-20 11:30:42

标签: ruby openssl

我在Ruby 1.8.7中使用OpenSSL,在Bash中使用OpenSSL来解码文件,但是使用Ruby代码,解密文件中的前16个字节是错误的。

这是我用Ruby获得的结果

cf e8 cf d1 12 e2 75 48  59 56 30 30 7d 7d 30 1b | wrong bytes
00 00 00 08 00 0c 01 1a  00 05 00 00 00 01 00 00 | good bytes
01 46 01 1b 00 05 00 00  00 01 00 00 01 4e 01 28 | good bytes
********************good bytes****************** | good bytes

这是我在Bash中使用OpenSSL得到的结果

ff d8 ff e1 22 d2 45 78  69 66 00 00 4d 4d 00 2a | correct bytes
00 00 00 08 00 0c 01 1a  00 05 00 00 00 01 00 00 | same bytes as in Ruby
01 46 01 1b 00 05 00 00  00 01 00 00 01 4e 01 28 | same bytes as in Ruby
*******************a lot of bytes*************** | same bytes as in Ruby

Ruby代码:

require 'openssl'

c = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
c.decrypt
c.key = "\177\373\2002\337\363:\357\232\251.\232\311b9\323"
c.iv = "00000000000000000000000000000001"

data = File.read("/tmp/file_crypt")
d = c.update(data)
d << c.final

file = File.open("/tmp/file_decrypt_ruby", "w")
file.write(d)
file.close

Bash OpenSSL命令:

openssl aes-128-cbc -d -in /tmp/file_crypt -out /tmp/file_decrypt_bash -nosalt -iv 00000000000000000000000000000001 -K 7ffb8032dff33aef9aa92e9ac96239d3

可以在此处下载编码文件:http://pastebin.com/EqHfpxjZ。使用“pbget”(如果有的话)下载文件。否则,复制文本,base 64解码,lzma解压缩。 (例如wget -q -O-“$ url”| base64 -d | lzma -d&gt;“$ TEMP”)。

通过pbget或上面的命令获得文件后,您需要进行一次64位最终解码:

base64 -d file_encode_base64 > encrypted_file

为确保您拥有正确的加密文件,MD5哈希值为:30b8f5e7d700c108cd9815c00ca1de2d

如果使用Bash版本的OpenSSL解码此文件,则会获得JPG格式的图片。

但是如果你使用Ruby版本,你会得到一个与picture.jpg不同的数据文件,前16个字节。

作为参考,这是我用来加密文件的命令:

openssl aes-128-cbc -e -in picture.jpg -out enc_file -nosalt -iv 00000000000000000000000000000001 -K 7ffb8032dff33aef9aa92e9ac96239d3

任何人都可以解释为什么我可以用Bash中的OpenSSL解码它,但是当我使用Ruby时得到的结果略有不同?

1 个答案:

答案 0 :(得分:2)

最后,它有效!答案实际上很简单。您的IV需要在Ruby代码中转换为二进制,类似于您转换密钥的方式。我在对此page的评论中找到了转换代码和解释。

试试这段代码:

require 'openssl'

cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
cipher.decrypt
cipher.key = "7ffb8032dff33aef9aa92e9ac96239d3".unpack('a2'*16).map{|x| x.hex}.pack('c'*16)
cipher.iv  = "00000000000000000000000000000001".unpack('a2'*16).map{|x| x.hex}.pack('c'*16)
data = File.read("/tmp/file_crypt")
decrypted = cipher.update(data) + cipher.final
file = File.open("/tmp/file_decrypt_ruby", "w")
file.write(decrypted)
file.close