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

为什么Ruby openssl aes 128 cbc的前16个字节是错误的?,ruby,openssl,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

我使用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
可在此处下载编码文件:。使用“pbget”(如果有的话)下载文件。否则,复制文本,对其进行base64解码,然后lzma对其进行解压缩。(例如wget-q-O-“$url”| base64-d | lzma-d>“$TEMP”)

一旦通过pbget或上述命令获得文件,您将需要执行最后一次base 64解码:

base64-d文件\u编码\u base64>加密\u文件

为确保您拥有正确的加密文件,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时得到的结果略有不同吗?

最后,它成功了!答案其实很简单。您的IV需要在Ruby代码中转换为二进制,类似于您转换密钥的方式。我在一篇评论中找到了转换代码和解释

请尝试以下代码:

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

谢谢你,请看我的编辑。非常感谢你。请查看我的新编辑。谢谢gtrig我没有这个MD5哈希。请查看我的新编辑。好的,我现在有正确的文件了。对于其他研究这个问题的人来说,pbget实际上做了一些事情。首先它对URL执行wget,然后执行base64解码,然后执行lzma解压缩。例如wget-q-O-“$url”| base64-d | lzma-d>“$TEMP”。因此,如果您抓取pastebin上的文本,您需要对其进行base64解码,lzma解压缩,然后再次对其进行base64解码,以获得问题中提到的加密文件。听起来像是你用pbput上传了加密文件。在这种情况下,在使用pbput之前不需要对其进行base64编码。pbput已经为您完成了。我现在可以复制您看到的内容。关于解密文件的前15个字节,一个有趣的事情是,它们的每个字节都有0x10或0x30的完全不同。当前15个中存在重复字节时,另一个中存在相应的重复字节。我不知道这是巧合还是问题所在的线索。
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