运行 openssl 加密功能更快
Run openssl encryption functions faster
这是一个与安全相关的问题here.
I am using this in my current PHP 7.0 setup which works fine. But because mcrypt has been replaced with openssl since 7.2, I am working to update the encrypt and decrypt functions with the ones posted 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";
#
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 次迭代不到一秒)
PBKDF2的迭代次数称为工作因子。如果迭代次数很高,那么工作因数(PBKDF2 需要执行的工作量)也很高。请注意,迭代次数与要执行的工作量成 线性,并且计算机变得更快(接近)指数.
请注意,PBKDF2 的实现可以在硬件和软件中加速。所以要小心,攻击者将能够更快地执行它们。 100,000其实是一个推荐量。
您的实现正确调用 PBKDF2 以获得少量字节(小于哈希值的输出)。如果您不这样做,那么 PBKDF2 基本上会被调用两次,而攻击者可能只调用一次就可以逃脱以验证密码猜测。因此请注意,不要更改代码以请求两个密钥,这只会减慢您的服务器速度。
但是,您在 encrypt
函数 中调用了 $key = getKey($password);
。这意味着密钥是为每次调用派生的。这当然不是很聪明:你应该 缓存密钥 直到不再需要它,然后直接销毁它。无需派生密钥 25 次。只是降低迭代次数是一种权宜之计,可以将很多优势还给攻击者。
这是一个与安全相关的问题here.
I am using this in my current PHP 7.0 setup which works fine. But because mcrypt has been replaced with openssl since 7.2, I am working to update the encrypt and decrypt functions with the ones posted 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";
#
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 次迭代不到一秒)
PBKDF2的迭代次数称为工作因子。如果迭代次数很高,那么工作因数(PBKDF2 需要执行的工作量)也很高。请注意,迭代次数与要执行的工作量成 线性,并且计算机变得更快(接近)指数.
请注意,PBKDF2 的实现可以在硬件和软件中加速。所以要小心,攻击者将能够更快地执行它们。 100,000其实是一个推荐量。
您的实现正确调用 PBKDF2 以获得少量字节(小于哈希值的输出)。如果您不这样做,那么 PBKDF2 基本上会被调用两次,而攻击者可能只调用一次就可以逃脱以验证密码猜测。因此请注意,不要更改代码以请求两个密钥,这只会减慢您的服务器速度。
但是,您在 encrypt
函数 中调用了 $key = getKey($password);
。这意味着密钥是为每次调用派生的。这当然不是很聪明:你应该 缓存密钥 直到不再需要它,然后直接销毁它。无需派生密钥 25 次。只是降低迭代次数是一种权宜之计,可以将很多优势还给攻击者。