我即将使用以下脚本来加密和解密某些数据。我正在使用它,因为我当前的加密在我们的新服务器上不起作用。我们目前正在使用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";
答案 0 :(得分:11)
初始化向量是使CBC(密码块链接)模式中的AES工作的一部分 - IV不是OpenSSL独有的。 CBC通过使用当前块对前一个块进行异或操作来工作。第一个块没有先前的块,因此IV用于此目的。
为什么这是必要的,需要对块密码的工作方式有所了解。如果没有这种链接和IV,我们将使用称为ECB或电子代码簿的AES模式。欧洲央行存在弱点,允许选择明文攻击,以及许多其他问题。
我建议花点时间研究CBC初始化向量的最佳实践。错误地使用它们会削弱AES的整体安全性。简短的解释是:
另请注意,此建议仅适用于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具有相同的密码。
答案 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),可以为给定的口头密钥生成此示例代码。