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 с открытым текстом, зашифрованным текстом или обоими (как в моем примере) и почему.

1 ответ

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

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)
    );
}
Другие вопросы по тегам