使用aes_256_cbc密码加密时的默认IV是多少?

时间:2016-06-30 13:54:52

标签: c++ encryption openssl aes block-cipher

我在一个文件中生成了一个随机的256位对称密钥,用于使用OpenSSL命令行加密某些数据,我需要稍后使用OpenSSL库以编程方式解密。我没有成功,我认为问题可能出在我使用(或不使用)的初始化向量中。

我使用此命令加密数据:

/usr/bin/openssl enc -aes-256-cbc -salt -in input_filename -out output_filename -pass file:keyfile

我使用以下调用来初始化数据的解密:

EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))

keyfile是一个vector<unsigned char>,它包含密钥的32个字节。我的问题是关于最后一个参数。它应该是密码算法的初始化向量。加密时我没有指定IV,因此必须使用某些默认值。

为该参数传递nullptr意味着&#34;使用默认值&#34;?是否为默认值null,并且没有任何内容添加到第一个密码块?

我应该提一下,我能够在不提供IV的情况下从命令行解密。

2 个答案:

答案 0 :(得分:8)

  

使用EVP_aes_256_cbc()[sic]密码加密时的默认IV是什么...

  为该参数传递nullptr是否意味着&#34;使用默认值&#34;?是否为默认值null,并且没有任何内容添加到第一个密码块?

没有。你必须提供它。为了完整起见,IV应该是不可预测的。

Non-Predictable Unique Random 略有不同。例如,SSLv3用于将最后一个密文块用于下一个块的IV。它是 Unique ,但它既不是 Random 也不是 Non-Predictable ,它使得SSLv3容易受到选择的明文攻击。

其他库会做一些聪明的事情,例如提供一个空向量(一个0&#39; s的字符串)。他们的攻击者感谢他们。另请参阅Stack Overflow上的Why is using a Non-Random IV with CBC Mode a vulnerability?和Crypto.SE上的Is AES in CBC mode secure if a known and/or fixed IV is used?

  

/usr/bin/openssl enc -aes-256-cbc...

  我应该提一下,我能够在不提供IV的情况下从命令行解密。

OpenSSL使用内部mashup /密钥派生函数来获取密码,并导出密钥和iv。它被称为EVP_BytesToKey,您可以在手册页中阅读它。手册页也说:

  

如果总密钥和IV长度小于摘要长度且使用MD5,则推导算法与PKCS#5 v1.5兼容,否则使用非标准扩展来导出额外数据。

一旦你知道要寻找什么,就有很多EVP_BytesToKey的例子。 Openssl password to key是Java中的How to decrypt file in Java encrypted with openssl command using AES中的一个。

  

EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))

  加密时我没有指定IV,因此必须使用某些默认值。

检查您的返回值。呼叫应该在路径的某个地方失败。可能不在EVP_DecryptInit_ex,但肯定在EVP_DecryptFinal之前。

如果没有失败,请提交错误报告。

答案 1 :(得分:7)

EVP_DecryptInit_ex是AES解密原语的接口。这只是解密OpenSSL加密格式所需的一部分。 OpenSSL加密格式没有很好的文档记录,但您可以从代码和一些文档向后工作。密钥和IV计算在EVP_BytesToKey文档中进行了解释:

   The key and IV is derived by concatenating D_1, D_2, etc until enough
   data is available for the key and IV. D_i is defined as:

           D_i = HASH^count(D_(i-1) || data || salt)

   where || denotes concatentaion, D_0 is empty, HASH is the digest
   algorithm in use, HASH^1(data) is simply HASH(data), HASH^2(data) is
   HASH(HASH(data)) and so on.

   The initial bytes are used for the key and the subsequent bytes for the
   IV.

“HASH”这里是MD5。实际上,这意味着你计算这样的哈希值:

Hash0 = ''
Hash1 = MD5(Hash0 + Password + Salt)
Hash2 = MD5(Hash1 + Password + Salt)
Hash3 = MD5(Hash2 + Password + Salt)
...

然后拉出密钥所需的字节数,然后拉出IV所需的字节数。对于AES-128,这意味着Hash1是关键,而Hash2是IV。对于AES-256,关键是Hash1 + Hash2(连接,未添加),Hash3是IV。

您需要去除前导Salted___标头,然后使用salt计算密钥和IV。然后,您将把这些内容提供给EVP_DecryptInit_ex

因为你在C ++中这样做,你可以直接挖掘enc代码并重复使用它(在验证其许可证与你的使用兼容之后)。

请注意,OpenSSL IV是随机生成的,因为它是涉及随机盐的散列过程的输出。第一个块的安全性不依赖于IV本身是随机的;它只需要一个特定的IV + Key对永远不会重复。只要随机盐永远不会重复,OpenSSL流程就可以确保。

有可能以这种方式使用MD5以泄漏信息的方式缠绕密钥和IV,但我从未见过声称这种情况的分析。如果你必须使用OpenSSL格式,我对它的第四代不会有任何犹豫。 OpenSSL格式存在的主要问题是它的蛮力很快(4轮MD5拉伸不够)并且没有任何认证。