这是与here发布的安全性相关的问题。
我在当前的PHP 7.0设置中使用的this正常工作。但是由于mcrypt从7.2开始已被openssl取代,因此我正在使用内置的here来更新加密和解密功能。
但这是因为该网页上有25个项目,因此执行时间很长,最终用户无法接受。
<?php
define("ENCRYPTION_KEY", "!@#$%^&*");
$StartTime = microtime(TRUE);
$e = [];
for ($i = 0; $i < 25; $i++)
{
$e[] = encrypt($i, ENCRYPTION_KEY);
}
echo number_format(microtime(TRUE) - $StartTime, 3)." seconds\n";
# https://stackoverflow.com/a/50373095/126833
function sign($message, $key) {
return hash_hmac('sha256', $message, $key) . $message;
}
function verify($bundle, $key) {
return hash_equals(
hash_hmac('sha256', mb_substr($bundle, 64, null, '8bit'), $key),
mb_substr($bundle, 0, 64, '8bit')
);
}
function getKey($password, $keysize = 16) {
return hash_pbkdf2('sha256',$password,'some_token',100000,$keysize,true);
}
function encrypt($message, $password) {
$iv = random_bytes(16);
$key = getKey($password);
$result = sign(openssl_encrypt($message,'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv), $key);
return bin2hex($iv).bin2hex($result);
}
function decrypt($hash, $password) {
$iv = hex2bin(substr($hash, 0, 32));
$data = hex2bin(substr($hash, 32));
$key = getKey($password);
if (!verify($data, $key)) {
return null;
}
return openssl_decrypt(mb_substr($data, 64, null, '8bit'),'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv);
}
?>
。
$ php encrypt-decrypt.php
6.288 seconds
有什么方法可以快速执行此操作? (不到一秒钟的时间进行25次迭代)
答案 0 :(得分:3)
PBKDF2的迭代次数称为工作因子。如果迭代次数很高,那么工作因子(PBKDF2需要执行的工作量)也就很高。请注意,迭代次数是线性且要执行的工作量很大,计算机以指数形式更快(接近) 。
请注意,PBKDF2实现可以在硬件和软件中加快。因此,请注意,攻击者将能够更快地执行它们。 100,000美元实际上是建议金额。
您的实现正确地调用了PBKDF2一小部分字节(小于哈希值的输出。如果不这样做,则PBKDF2基本上被调用了两次,而攻击者可能只调用一次来验证密码猜测。请注意,不要更改代码来要求输入两个密钥,这只会减慢服务器速度。
但是,您在$key = getKey($password);
函数中调用了encrypt
。这意味着将为每个呼叫派生密钥。这当然不是很聪明:您应该缓存密钥,直到不再需要它为止,然后直接销毁它。无需导出密钥25次。只是降低迭代次数是一种临时解决方案,可以将大量优势移交给攻击者。