我需要加密一些数据并在稍后的时间点解密。数据与特定用户相关联。我收集了两种可能的解决方案......
1:第一个来自官方文档(示例#1 @ http://php.net/manual/en/function.mcrypt-encrypt.php):
function encrypt($toEncrypt)
{
global $key;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $toEncrypt, MCRYPT_MODE_CBC, $iv));
}
function decrypt($toDecrypt)
{
global $key;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$toDecrypt = base64_decode($toDecrypt);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, substr($toDecrypt, $iv_size), MCRYPT_MODE_CBC, substr($toDecrypt, 0, $iv_size)));
}
使用以下命令生成一次密钥:
pack('H*', bin2hex(openssl_random_pseudo_bytes(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC))));
1.1:我注意到加密结果总是以两个等号('==')结尾。为什么?- 在 encrypt() 和 decrypt() 中分别使用 bin2hex() 和 hex2bin() 而不是 base64_encode()/base64_decode() 不会产生这些结果。
1.2:使用 bin2hex()/hex2bin() 会对结果产生任何影响(长度除外)吗?
1.3:似乎有一些讨论是否在解密时对返回结果调用修剪函数(这也适用于下面的解决方案)。为什么这是必要的?
2:第二种解决方案来自这里,Stackoverflow(https://stackoverflow.com/questions/9262109/php-simplest-two-way-encryption):
function encrypt($key, $toEncrypt)
{
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $toEncrypt, MCRYPT_MODE_CBC, md5(md5($key))));
}
function decrypt($key, $toDecrypt)
{
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($toDecrypt), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
}
我知道这两种按键处理方法是可以互换的,我特意让它们在这方面有所不同,以突出可能的解决方案,请随意混合搭配。
我个人觉得第一个提供了更严格的安全性,因为密钥和初始化向量都是正确随机的。然而,第二种解决方案确实提供了某种形式的不可预测性,因为每个加密数据的密钥都是唯一的(即使它受到 md5() 的弱随机化的影响)。例如,密钥可以是用户名。
3:那么,哪一个更可取?自从 Stackoverflow 的答案获得了 105 票以来,我有点不知所措。其他想法,提示?
4:额外的问题!:我在服务器安全方面并不是非常聪明,但显然获得对 PHP 文件的访问权限会暴露密钥,这直接导致加密无用,假设攻击者也可以访问D B。有什么办法可以隐藏钥匙吗?
感谢您的阅读,祝您有美好的一天!