如何从 encrypted_strings 中提取加密方法生成的 IV 向量

How to extract the IV vector generated by encrypt method from encrypted_strings

我无法从 encrypted_strings 库中为我提供的特定密码提取使用 encrypt 方法生成的 IV。从文档中,我看到此方法使用 C 库基于密码生成密钥和 iv,该库调用与 openssl 相同的方法来生成密钥和 iv:EVP_BytesToKey.

我想做的是能够为我指定的任何密码打印 IV,这样我就可以将加密移植到另一种语言。

你能想出从密码中 extract/print 这个 IV 向量的方法吗?

这些是该库使用的算法、模式和填充的详细信息:

下面的 ruby 脚本打印出加密消息,但不知道使用了哪个 iv。

#!/usr/bin/ruby
require 'encrypted_strings'

data = 'Whackabad'
password = 'bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ'

encrypted_data = data.encrypt(:symmetric, :password => password)
printf "Data: #{data}\n"
printf "Encrypted Data: #{encrypted_data}"

我尝试使用 openssl,因为它允许我打印使用 [​​=16=] 选项生成的 iv 和密钥,但它使用 PKCS7 填充而不是 PKCS5。因此,如果我 运行 下面的命令,不会打印与上面的 ruby 代码相同的加密字符串。

echo -n 'Whackabad' | openssl enc -des-ede3-cbc -nosalt -a -k bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ

注意: -a:base64 编码,-k:密码和回显 -n:从字符串中删除新行,因此它的大小与字符串中的 ruby 完全相同。

如果我添加 -nopad 选项,我不知道如何填充输出以获得完全相同的加密结果。

如有任何帮助,我们将不胜感激

PKCS7 padding 与PKCS5基本相同。你在命令行上得到不同结果的原因是它只使用一个散列迭代,其中 encrypted_strings does 2048 iterations by default.

使用的函数

使用的函数,EVP_BytesToKey is described in the OpenSSL wiki,其中包含算法的详细信息。在 Ruby 中重现它可能看起来像这样(使用 MD5 和 2048 次迭代):

def hash(d, count)
  count.times do
    d = OpenSSL::Digest.digest('md5', d)
  end
  d
end

password = 'bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ'

bytes = ''
last = ''

# For des-ede3-cbc, 24 byte key + 8 byte IV = 32 bytes.
while bytes.length < 32
  last = hash(last + password, 2048)
  bytes << last
end

key = bytes[0...24]
iv = bytes[24..-1]

您可以使用这些值来解密代码的结果(先添加 require 'base64'):

# This is the result of your code:
encrypted_data = "AEsDXVcgh2jsTjlDgh+REg=="

# enrypted_strings produces base64 encoded results, so we decode first
encrypted_data = Base64.decode64(encrypted_data)

cipher = OpenSSL::Cipher.new('des-ede3-cbc')
cipher.decrypt
cipher.key = key
cipher.iv = iv

plain = cipher.update(encrypted_data) + cipher.final

puts plain #=> "Whackabad"