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

别说谁变了你拦得住时间么 提交于 2019-12-25 06:46:42

问题


I'm having troubles to extract the IV generated with the encrypt method from encrypted_strings library for a specific password I provide. From the documentation, I see that this method generates a key and iv based on a password using a C library that calls the same method as openssl to generate the key and iv: EVP_BytesToKey.

What I'm trying to do is to be able to print the IV for any password I specify so I can port the encryption to another language.

Can you think of any method to extract/print this IV vector from a password?

These are the details of the algorithm, mode and padding this library uses:

  • ALGO: DES-EDE3
  • MODE: CBC
  • PADDING: PKCS5

The ruby script below prints out the encrypted message but no clue which iv was used.

#!/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}"

I tried to use openssl as it allows me to print the iv and key generated using -p option but it uses a PKCS7 padding instead of PKCS5. So if I run the command below, doesn't print the same encrypted string as the ruby code above.

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

NOTE: -a: base64 encode, -k: password, and echo -n: removes the new line from the string so its exactly the same size as the ruby in string.

If I add -nopad option, I don't know how to pad the output to get exactly the same encrypted result.

Any help would be much appreciated


回答1:


PKCS7 padding is basically the same as PKCS5. The reason you get a different result on the command line is that it only uses a single hash iteration, where the function used by encrypted_strings does 2048 iterations by default.

The function used, EVP_BytesToKey is described in the OpenSSL wiki, which include details of the algorithm. Reproducing it in Ruby might look something like this (using MD5 and 2048 iterations):

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]

You can use these values to decrypt the result of your code (add require 'base64' first):

# 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"


来源:https://stackoverflow.com/questions/42420098/how-to-extract-the-iv-vector-generated-by-encrypt-method-from-encrypted-strings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!