【问题标题】:Why are the first 16 bytes wrong with Ruby openssl aes 128 cbc?为什么 Ruby openssl aes 128 cbc 的前 16 个字节有误?
【发布时间】:2013-05-20 11:30:42
【问题描述】:

我使用 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 > "$TEMP")。

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

base64 -d file_encode_base64 &gt; 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 时得到的结果略有不同?

【问题讨论】:

  • 谢谢 gtrig 请看我的编辑。
  • 非常感谢 gtrig。请查看我的新编辑。
  • 感谢 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个字节中有重复字节时,另一个有相应的重复字节。我不知道这只是巧合,还是说明问题所在。

标签: ruby openssl


【解决方案1】:

终于成功了!答案其实很简单。您的 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

【讨论】:

    猜你喜欢
    • 2019-08-17
    • 2020-04-15
    • 2013-08-11
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多