如何安全地为 AES CBC 加密生成 IV?

Posted

技术标签:

【中文标题】如何安全地为 AES CBC 加密生成 IV?【英文标题】:How to securely generate an IV for AES CBC Encryption? 【发布时间】:2011-11-08 23:52:10 【问题描述】:

我从事一些加密货币的工作。

我使用 AES 256 和 CBC 模式 我使用 OPENSSL

我知道以下事情(来源 = ***):

初始化向量应该是:

唯一性:对于使用给定密钥加密的任何消息,不得重复 不可预测:观察到任意数量的消息及其 IV 的攻击者不应该有任何信息来预测下一条成功概率大于 50% 每比特(即无法区分随机)

我的问题是,如何使用 OPENSSL 和 php 安全地生成 IV?我知道 lib mcrypt (https://php.net/manual/en/function.mcrypt-create-iv.php) 中有这样的功能

我没有找到任何可以使用 OPENSSL(生成唯一且不可预测的 IV)的方法。

【问题讨论】:

你在验证你的密文吗? 【参考方案1】:

使用 Thomas 提出的相同的东西更舒服:

private function genIv()

    $efforts = 0;
    $maxEfforts = 50;
    $wasItSecure = false;

    do
    
        $efforts+=1;
        $iv = openssl_random_pseudo_bytes(16, $wasItSecure);
        if($efforts == $maxEfforts)
            throw new Exception('Unable to genereate secure iv.');
            break;
        
     while (!$wasItSecure);

    return $iv;

【讨论】:

【参考方案2】:

使用openssl_random_pseudo_bytes(最好将第二个参数设置为现有变量,然后您应该测试它是否设置为TRUE)。这将生成具有适当随机性特征的 IV。

$wasItSecure = false;
$iv = openssl_random_pseudo_bytes(16, $wasItSecure);
if ($wasItSecure) 
    // We're good to go!
 else 
    // Insecure result. Fail closed, do not proceed.

另外,PHP 7 提供了random_bytes(),这要简单得多。

【讨论】:

如何确定 IV 的合适长度? 请注意,openssl_random_pseudo_bytes 的第二个可选参数是对变量的引用。当生成的字符串被认为是“密码学强”时,它的值由 openssl 设置。见openssl.org/docs/crypto/RAND_bytes.html 正确。第二个参数通过引用传递,并且仅当使用的算法具有加密强度时,调用后才包含 true。请参阅下面的示例和正确用法的答案。 注意:在 PHP 7 中,最好只使用random_bytes()。它比 OpenSSL 更可靠(更可能是安全的)。 @foochow 也许你正在寻找openssl_cipher_iv_length(),见php.net/manual/en/function.openssl-cipher-iv-length.php【参考方案3】:

您可以使用 openssl_random_pseudo_bytes(len, &crypto_stron)

第一个参数是你想要的字节长度。如果您将其用于其中一种开放式 ssl 方法,则可以使用函数 openssl_cipher_iv_length(method) 来获取所用方法的正确长度。

第二个参数 &crypto_strong 允许您传入一个布尔变量,该变量将根据所使用的算法是否具有加密安全性而设置为 true 或 false。然后,您可以检查此变量并在变量返回 false 时正确处理它。它永远不会发生,但如果发生了,那么您可能想知道。

以下是正确使用的示例:

$method = 'aes-256-cbc';
$ivlen = openssl_cipher_iv_length($method);
$isCryptoStrong = false; // Will be set to true by the function if the algorithm used was cryptographically secure
$iv = openssl_random_pseudo_bytes($ivlen, $isCryptoStrong);
if(!$isCryptoStrong)
    throw new Exception("Non-cryptographically strong algorithm used for iv generation. This IV is not safe to use.");

欲了解更多信息,请参阅:

http://php.net/manual/en/function.openssl-random-pseudo-bytes.php http://php.net/manual/en/function.openssl-cipher-iv-length.php http://php.net/manual/en/function.openssl-get-cipher-methods.php

【讨论】:

以上是关于如何安全地为 AES CBC 加密生成 IV?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在没有 iv 的情况下在 openssl 中运行 aes-128-cbc 加密?

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

JAVA AES CBC 加密 解密

AES128 CBC模式加密中初始化向量IV怎么设定?

python encrypt 实现AES加密

AES GCM加密模式的初始向量IV怎么确定