问题
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