什么是openssl iv,为什么我需要一把钥匙和一个静脉?

Tho*_*ams 14 encryption secret-key initialization-vector php-openssl

我即将使用以下脚本来加密和解密某些数据.我正在使用它,因为我当前的加密在我们的新服务器上不起作用.我们目前正在使用mcrypt,所以我想更改为openssl.

在我们的数据库中,我们使用aes加密,它使用128位密钥,所以我知道密钥是什么,但我不知道openssl iv是什么?为什么我需要钥匙和iv.

我即将使用的代码就是这个,我在网站上找到了,因为我不太了解加密.

显然我会修改它,以便将密钥保存在其他地方.

function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = 'This is my secret key';
    $secret_iv = 'This is my secret iv';

    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    }
    else if( $action == 'decrypt' ){
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}

$plain_txt = "This is my plain text";
echo "Plain Text = $plain_txt\n";

$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txt\n";

$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txt\n";

if( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";

echo "\n";
Run Code Online (Sandbox Code Playgroud)

vcs*_*nes 17

初始化向量是使CBC(密码块链接)模式中的AES工作的一部分 - IV不是OpenSSL独有的.CBC通过使用当前块对前一个块进行异或操作来工作.第一个块没有先前的块,因此IV用于此目的.

为什么这是必要的,需要了解分组密码的工作原理.如果没有这种链接和IV,我们将选择一种名为ECB或电子代码簿的AES模式.欧洲央行存在弱点,允许选择明文攻击,以及许多其他问题.

我建议花一些时间与CBC初始化向量的最佳实践.错误地使用它们会削弱AES的整体安全性.简短的解释是:

  • IV应该是随机的并由CSPRNG生成.
  • IV不应重复使用.也就是说,不要用相同的IV加密明文"A"和明文"B".每条记录都应该有自己的IV.
  • IV不是关键的秘密.它可以与密文一起以明文形式存储.

另请注意,此建议仅适用于AES-CBC.如果您曾调查其他AES模式,例如GCM,则不适用.

  • @ThomasWilliams尽管如此,你不应该自己实现这一点.您对该主题缺乏了解意味着您很可能会犯一个实施错误,并在您的安全性方面留下一个漏洞.只是我的两分钱.找到更高级别的库. (2认同)
  • 我已经把一切都搞定了。我对 openssl 缺乏了解。然而,我已经用 C++ 和 php 编程很长时间了。自从提出问题以来,我已经阅读了很多有关它的内容,并且我已经将其全部实施并运行。我曾经用 C++ 编写过自己的加密算法,但最好使用经过尝试和测试的算法,而不是您自己的代码。 (2认同)

alb*_*o56 10

假设两个用户有密码“公主”,你用密钥“some-key”对他们进行编码,他们都会有相同的加密结果:

| User       | Encrypted password    |
|------------|-----------------------|
| a          | sN7vIFg=              |
| b          | sN7vIFg=              |
Run Code Online (Sandbox Code Playgroud)

这意味着,如果有人用不同的方式计算出用户a的真实密码是“公主”,而他们的加密密码是“sN7vIFg=”,那么任何拥有加密密码“sN7vIFg=”的用户都可以被视为拥有密码“公主” ”。

但是,如果您对每个都使用随机 IV,那么如果您有权访问加密数据,则更难猜测底层密码。

| User       | Encrypted password    | IV             |
|------------|-----------------------|----------------|
| a          | sN7vIFg=              | h²ÓIF8]h%L     |
| b          | BjZAzrA=              | VÂøíiøÚØò?     |
Run Code Online (Sandbox Code Playgroud)

现在,即使有人可以访问上述数据,他们也无法弄清楚用户 a 和 b 具有相同的密码。

另请参阅“真盐”与“初始化向量”相同吗? .


Con*_*ish 6

我想你可能混淆了“散列密钥”和“iv”(天知道我在开始加密时做过)。散列键正是你所做的。对于 iv,每次使用相同密钥进行加密时,您应该使用不同的随机数据。(我的背景:我必须构建一个 pdo 安全会话处理程序来加密/解密会话数据,所以我最终使用 openssl 扩展实现了 AES-256-CBC)

如果有人来这里只是一个小提示。

// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
Run Code Online (Sandbox Code Playgroud)

不是生成 iv + 不需要 secret_iv 的正确方法,因为 iv 必须尽可能随机。不要将它(或理解它)与散列相同。

由于您可以访问 openssl 扩展,因此有一种更好/更安全的方式为所选密码生成 iv,openssl 还可以告诉您密码 iv 的正确长度:

$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));
Run Code Online (Sandbox Code Playgroud)

它将采用二进制格式,因此如果您需要以十六进制形式使用 bin2hex($iv)。如果您需要将生成的 iv 存储在 mysql 中,我以原始格式存储它(字段类型 varbinary,binary 也有效)。

还有一件事。您在 openssl_encrypt 和 _decrypt 中都将 $options 标记设置为 0,这意味着“如果设置为 true 将作为原始输出数据返回,否则返回值是 base64 编码的”。

  • 喜欢重新创建 $iv 的解释 (2认同)