Ste*_*eve 14 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
Run Code Online (Sandbox Code Playgroud)
我正在使用以下调用来初始化数据的解密:
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
Run Code Online (Sandbox Code Playgroud)
keyfile是一个vector<unsigned char>保存密钥的32个字节.我的问题是关于最后一个参数.它应该是密码算法的初始化向量.加密时我没有指定IV,因此必须使用某些默认值.
为该参数传递nullptr是否意味着"使用默认值"?是否为默认值,并且没有任何内容添加到第一个密码块?
我应该提一下,我能够在不提供IV的情况下从命令行解密.
使用EVP_aes_256_cbc()[sic]密码加密时的默认IV是什么...
为该参数传递nullptr是否意味着"使用默认值"?是否为默认值,并且没有任何内容添加到第一个密码块?
空无一人.你必须提供它.为了完整起见,IV应该是不可预测的.
Non-Predictable与Unique和Random略有不同.例如,SSLv3过去常常使用最后一个密文块作为下一个块的IV.它是唯一的,但它既不是随机也不是非可预测的,它使SSLv3容易受到选择的明文攻击.
其他库做一些聪明的事情,比如提供一个空向量(一个0的字符串).他们的攻击者感谢他们.另请参阅为什么使用具有CBC模式的非随机IV漏洞?如果使用已知和/或固定的IV,则在堆栈溢出和CBC模式下的AES是否安全?在Crypto.SE上.
/usr/bin/openssl enc -aes-256-cbc...
我应该提一下,我能够在不提供IV的情况下从命令行解密.
OpenSSL使用内部mashup/key派生函数,它接受密码,并导出密钥和iv.它被调用EVP_BytesToKey,您可以在手册页中阅读它.手册页还说:
如果总密钥和IV长度小于摘要长度并且使用MD5,则导出算法与PKCS#5 v1.5兼容,否则使用非标准扩展来导出额外数据.
EVP_BytesToKey一旦你知道要寻找什么,就有很多例子.密钥的Openssl密码是C中的一个.如何在Java中使用AES在一个用openssl命令加密的Java中解密文件.
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
加密时我没有指定IV,因此必须使用某些默认值.
检查您的退货值.呼叫应该在路径的某个地方失败.也许不是EVP_DecryptInit_ex,但肯定在之前EVP_DecryptFinal.
如果没有失败,请提交错误报告.
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.
Run Code Online (Sandbox Code Playgroud)
"哈希"这里是MD5.在实践中,这意味着你计算这样的哈希:
Hash0 = ''
Hash1 = MD5(Hash0 + Password + Salt)
Hash2 = MD5(Hash1 + Password + Salt)
Hash3 = MD5(Hash2 + Password + Salt)
...
Run Code Online (Sandbox Code Playgroud)
然后拉出密钥所需的字节数,然后拉出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拉伸不够)并且缺乏任何身份验证.