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

时间:2016-09-09 13:31:54

标签: encryption secret-key php-openssl initialization-vector

我即将使用以下脚本来加密和解密某些数据。我正在使用它,因为我当前的加密在我们的新服务器上不起作用。我们目前正在使用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";

4 个答案:

答案 0 :(得分:11)

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

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

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

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

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

答案 1 :(得分:3)

我认为你可能混淆了“哈希键”和“静脉”(上帝知道我在开始加密时做了)。哈希键正是你所做的。对于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);

不是生成iv +的正确方法,不需要secret_iv,因为iv必须是随机的。不要像散列那样对待它(或理解它)。

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

$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));

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

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

答案 2 :(得分:0)

假设两个用户的密码为“公主”,而您使用密钥“ some-key”对它们进行编码,则它们将具有相同的加密结果:

| User       | Encrypted password    |
|------------|-----------------------|
| a          | sN7vIFg=              |
| b          | sN7vIFg=              |

这表示如果某人以其他方式弄清楚用户a的真实密码为“公主”,而其加密密码为“ sN7vIFg =“,则任何具有加密密码“ sN7vIFg =”的用户都可以被视为具有密码“公主”。

但是,如果您每个都使用随机IV,那么如果您可以访问加密数据,则更难猜测基本密码。

| User       | Encrypted password    | IV             |
|------------|-----------------------|----------------|
| a          | sN7vIFg=              | h²ÓIF8]h%L     |
| b          | BjZAzrA=              | VÂøíiøÚØò▓     |

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

另请参阅Is “real salt” the same as “initialization vectors”?

答案 3 :(得分:0)

我通常这样设置:

    // PHP Function to encrypt
function encrypt_AES_CBC ($plaintext) {
    $method = "aes-256-cbc";
    $key = "DADA068D255130F7AB5965BD47692E359EE7B0CBC81D9DAD42665B71F7807A4E";
    $bkey = hex2bin($key);
    $iv = hex2bin(md5(microtime().rand()));
    $data = openssl_encrypt($plaintext, $method, $bkey, OPENSSL_RAW_DATA, $iv);
    return base64_encode($iv.$data);
}
// PHP Function to decrypt
function decrypt_AES_CBC ($encryptedText) {
    $method = "aes-256-cbc";
    $key = "DADA068D255130F7AB5965BD47692E359EE7B0CBC81D9DAD42665B71F7807A4E";
    $bkey = hex2bin($key);
    $decoded = base64_decode($encryptedText);
    $iv = substr($decoded, 0, 16);
    $data = substr($decoded, 16);
    return openssl_decrypt( $data, $method, $bkey, OPENSSL_RAW_DATA, $iv );
}

我创建了一个 FileMaker 插件 (acfplugin),可以为给定的口头密钥生成此示例代码。