C++ 使用aes_256_cbc密码加密时默认的IV是什么?
我在一个文件中生成了一个随机的256位对称密钥,用于使用OpenSSL命令行加密某些数据,稍后需要使用OpenSSL库以编程方式对其进行解密。我没有成功,我认为问题可能在于我正在使用(或未使用)的初始化向量 我使用以下命令加密数据:C++ 使用aes_256_cbc密码加密时默认的IV是什么?,c++,encryption,openssl,aes,block-cipher,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_DecryptIni
/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
是一个包含键的32字节的向量。我的问题是关于最后一个参数。它应该是密码算法的初始化向量。加密时我没有指定IV,所以一定使用了一些默认值
为该参数传递nullptr是否意味着“使用默认值”?默认值为空,并且没有向第一个密码块添加任何内容
我应该提到,我可以在不提供IV的情况下从命令行解密。EVP\u DecryptInit\u 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.
这里的“散列”是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\uuuuuuuuuuuu
头,然后使用salt来计算密钥和IV。然后你就有了要输入EVP\u DecryptInit\u ex
的片段
因为你在C++中这样做,你可以通过代码> Enc>代码>代码来重用它(在验证它的许可证与你的使用兼容)之后。
请注意,OpenSSL IV是随机生成的,因为它是包含随机salt的哈希过程的输出。第一个区块的安全性并不取决于IV本身是随机的;它只要求特定的IV+密钥对永远不要重复。OpenSSL过程可以确保,只要随机盐不再重复
以这种方式使用MD5可能会以泄露信息的方式缠绕密钥和IV,但我从未见过有分析声称这一点。如果您必须使用OpenSSL格式,我不会对它的IV代有任何犹豫。OpenSSL格式的最大问题是它很快就可以使用暴力(4轮MD5不够扩展),而且它缺乏任何身份验证
使用EVP_aes_256_cbc()[sic]密码加密时,默认的IV是什么…
为该参数传递nullptr是否意味着“使用默认值”?默认值为空,并且没有向第一个密码块添加任何内容
没有。你必须提供它。为了完整性,IV应该是不可预测的
“不可预测”与“唯一”和“随机”略有不同。例如,SSLv3使用最后一个密文块作为下一个块的IV。它是唯一的,但既不是随机的,也不是不可预测的,并且它使SSLv3容易受到选择的明文攻击
其他库做了一些聪明的事情,比如提供一个空向量(一个0的字符串)。袭击者为此感谢他们。另请参见关于堆栈溢出和关于Crypto.SE的内容
/usr/bin/openssl enc-aes-256-cbc…
我应该提到,我可以在不提供IV的情况下从命令行解密
OpenSSL使用一个内部mashup/key派生函数,该函数接受密码,并派生一个key和iv。它被调用,您可以在手册页中了解它。手册页还说:
如果总密钥和IV长度小于摘要长度且使用MD5,则派生算法与PKCS#5 v1.5兼容,否则使用非标准扩展来派生额外数据
一旦你知道要寻找什么,就有很多例子可以说明EVP_BytesToKey
。在C中是一个,在Java中是一个
EVP_DecryptInit_ex(ctx,EVP_aes_256_cbc(),nullptr,keyfile.data(),nullptr))
加密时我没有指定IV,所以一定使用了一些默认值
检查您的返回值。呼叫应该在路径的某个地方失败。也许不是在EVP\u DecryptInit\u ex
,但肯定是在EVP\u decryptinfinal
之前
如果没有失败,请提交错误报告。使用no IV(或固定默认值)不会严重破坏加密的强度吗?据我所知,IV的目的是确保相同的明文不会生成相同的密文。所以需要有一个IV,它不需要是秘密的,它只需要对你加密的所有东西都是唯一的。不使用密码(或固定密码)听起来是一个非常糟糕的主意。我不是密码专家,也不在电视上播放密码,所以我真的没有资格回答(因此,为什么上面只是一个评论)。作为一个非专家,我猜只要每次密钥都是唯一的,那么它可能就没问题了,但作为一个对加密知之甚少的实用主义者,无论如何,我可能也会使用随机IV,我发现了一些关于这方面的信息:这里的公认答案似乎与我最初的直觉一致,即使用固定IV会降低强度(在攻击者试图强行破解密钥的情况下)。所以每次我都会使用(真正的)随机IV,即使键是唯一的。@JesperJuhl-每种模式通常有不同的要求。CBC通常需要一个不可预测的IV。我更新了我的答案以提供参考。这不是失败