безопасность — PHP двойная рандомизированная проверка hmac для предотвращения атаки по времени

Чтобы предотвратить атаки по времени для сравнения хеш-строк, необходимо выполнить дополнительную подпись HMAC, чтобы рандомизировать процесс проверки (см. https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/).

В дополнение ко второму хешированию HMAC для каждого хеша, к обоим добавляется случайная соль произвольной длины, чтобы сделать время / процесс хеширования еще менее предсказуемым.

Моя реализация этого выглядит так:

function hmac_verify ($hash_original, $message, $key) {

$hmac_salt = '...'; // was added at the original HMAC signing
$random_salt = openssl_random_pseudo_bytes (rand(16,96));

$raw_hash = hash_hmac('sha512', $message . $hmac_salt, $key, true);
$hash_compare = base64_encode ($raw_hash); // $hash_original is in base64
$hash_compare_safe = hash_hmac('sha512', $hash_compare, $random_salt, true);
$hash_original_safe = hash_hmac('sha512', $hash_original, $random_salt, true);

if ($hash_compare_safe === $hash_original_safe) return true;
else return false;

}

Функция вызывается таким образом после расшифровки зашифрованного текста, чтобы проверить результат дешифрования:

if (!hmac_verify ($hmac_hash, $plaintext . $cipher_text, $key . $iv)) return "HASH ERROR";

Это успешно предотвратит атаку времени? Я делаю что-нибудь ненужное? Можно ли что-то улучшить?

Второй вопрос: целесообразнее ли выполнять проверку HMAC с открытым текстом, зашифрованным текстом или обоими (как в моем примере) и почему.

2

Решение

Я оставил несколько комментариев, пока я читал вашу функцию. Это не анализ после прочтения всего этого, скорее это то, о чем я сразу думаю, читая это.

function hmac_verify ($hash_original, $message, $key) {
##
# Nitpick: A variable named $hash_original will prime people who read
# your code to think of simple hash functions rather than HMAC
##

$hmac_salt = '...'; // was added at the original HMAC signing
##
# What is this? $hmac_salt? Looks like a hard coded-salt (a.k.a. pepper).
# I wouldn't trust this with my life.
##

$random_salt = openssl_random_pseudo_bytes (rand(16,96));
##
# Why are you bothering to randomize this? Just use a static value
# approximating the output size of the hash function (i.e. 64).
##

$raw_hash = hash_hmac('sha512', $message . $hmac_salt, $key, true);
$hash_compare = base64_encode ($raw_hash); // $hash_original is in base64
$hash_compare_safe = hash_hmac('sha512', $hash_compare, $random_salt, true);
##
# Ah, yeah, don't pepper. HMAC is secure.
##
$hash_original_safe = hash_hmac('sha512', $hash_original, $random_salt, true);

if ($hash_compare_safe === $hash_original_safe) return true;
else return false;
##
# Why not just do this?
# return $hash_compare_safe === $hash_original_safe;
##

}

Итак, я бы настоятельно рекомендовал разделить это на два отдельных механизма: один, который вычисляет MAC, и другой, который сравнивает строки в постоянное время (например, PHP 5.6 hash_equals() делает).

function hmac_verify ($hmac, $message, $key)
{
$calc = hash_hmac('sha512', $message, $key, true);
return hmac_equals($hmac, $calc);
}

function hmac_equals($hmac, $calc)
{
$random = openssl_random_pseudo_bytes(64);
return (
hash_hmac('sha512', $hmac, $random)
===
hash_hmac('sha512', $calc, $random)
);
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]