2017-02-23 13 views
0

我提供用于提供特定密码的方法从encrypted_strings库中生成的IV所产生的麻烦。从文档中,我看到这个方法基于密码使用C库生成密钥和iv,该库调用与openssl相同的方法来生成密钥和iv:EVP_BytesToKey。如何从encrypted_strings中提取由加密方法生成的IV矢量

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

你能想到任何方法从密码中提取/打印这个IV向量吗?

这些都是该算法,模式和填充这个库使用的细节:

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

红宝石下面的脚本打印出加密的消息,但不知道使用了哪个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,因为它可以让我打印使用-p选项生成的IV和关键,但它采用的是PKCS7填充,而不是PKCS5。所以如果我运行下面的命令,不会打印与上面的ruby代码相同的加密字符串。

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

注: -a:使用Base64编码,-k:密码和echo -n:将删除字符串,其大小完全一样的,如串红宝石的新生产线。

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

任何帮助,将不胜感激

+0

一个经常使用的方法是简单地用IV加前缀加密的数据。在这种情况下,只需从第一个block_length字节中获取IV,然后跳过该数据即可获得加密数据。 – zaph

+0

@zaph我不确定ruby代码实际上是用IV加密数据的前缀。如果是这样,我应该只取第一个block_length字节? – rakemous

回答

3

PKCS7填充是基本相同PKCS5。在命令行上得到不同结果的原因是它只使用单个哈希迭代,其中由encrypted_stringsdoes 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" 
+0

太棒了!非常感谢这个答案。它真的帮助了我! – rakemous

+0

这就是OpenSSL就是这样一个POS的原因之一,这个文件是懒惰的,不应该有必要去源代码来确定默认值! – zaph

+0

@Matt - 请原谅我的无知。文件差距在哪里?命令'openssl enc'记录在['enc'手册页](https://www.openssl.org/docs/man1.0.2/apps/enc.html)中。该文档指出:*“所有分组密码通常使用PKCS#5填充,也称为标准块填充”*。同样,['EVP_BytesToKey'手册页](https://www.openssl.org/docs/man1.0.2/crypto/EVP_BytesToKey.html)记录了OpenSSL函数。 – jww

相关问题