Чому std :: hash не гарантовано буде детермінованим?


28

Згодом ми використовуємо N4140 (стандарт C ++ 14).


Відповідно до § 17.6.3.4 Вимоги до хешу ,

Повернене значення залежить лише від аргументу k протягом тривалості програми .

[Примітка. Таким чином, всі оцінки виразу h(k)з однаковим значенням kдають однаковий результат для заданого виконання програми . - кінцева примітка]

і § 20.9.12 Хеш-шаблон шаблону класу говорить

...

інстанція hash<Key>:

(1.1) - відповідають вимогам Hash (17.6.3.4) ...

(1.2) - ...


Це означає, що хеш-значення value(тобто hash<decltype(value)>(value)) може приймати інше значення при перезапуску програми.

Але чому? Це обмеження було не в Стандарті C ++ 11, а в Стандарті C ++ 14, C ++ 17 і C ++ 20. Як користувач (а не розробник STL), було б дуже корисно, якби вони std::hashбули детермінованими. Чи є якісь математичні труднощі в реалізації детермінованої хеш-функції? Але хеш-функції, які ми щодня використовуємо (наприклад, застарілі md5sumабо безпечніші sha256), все є детермінованими. Чи є проблема ефективності?


7
"... Функції хеша потрібні лише для отримання одного і того ж результату для одного і того ж вводу в рамках одного виконання програми; це дозволяє солоним хешам, що запобігають атакам відмови в обслуговуванні зіткнення ." Джерело: en.cppreference.com/w/cpp/utility/hash
Річард Криттен

5
Це дозволяє детермінованому алгоритму приймати недетерміновані введення. Наприклад, значення вказівника. Незмінна структура даних може хешувати адреси своїх внутрішніх даних, що може бути набагато швидше, ніж хеш-вміст.
Джон Кугельман

4
Ця відповідь має кілька приємних посилань, чому ви не хочете детермінізму.
NathanOliver

3
Не загрожуйте цим обмеженням, але робіть стандартні обмеження трохи менш суворими.
Marek R

4
Ось повне пояснення, чому обмеження були послаблені.
Marek R

Відповіді:


17

Не потрібно, щоб хеш-функція була детермінованою між запусками, але ви все одно можете надати свій власний хеш, наприклад, для не упорядкованих контейнерів, якщо це поведінка, на яку ви покладаєтесь.

Щодо чому, cppreference говорить:

Функції хешу необхідні лише для отримання одного і того ж результату для одного і того ж вводу в рамках одного виконання програми; це дозволяє солоним хешам, які запобігають атакам відмови в обслуговуванні зіткнення.

Якщо Hashвимоги вказують, що це детерміновано, ви не зможете надати солоний хеш, не порушуючи вимоги.

Ось власне пояснення чому


7

Ця відповідь (та посилання в ній), запропоновані @NathanOliver, в кінцевому рахунку корисні. Дозвольте навести важливі частини.

Для некриптографічної хеш-функції можна заздалегідь обчислити масивні входи з однаковим хешованим значенням, щоб алгоритмічно сповільнити не упорядковані контейнери, і це призведе до атаки відмови в обслуговуванні.

випуску 2291. std :: хеш вразливий для зіткнення DoS-атаки )

З цієї причини мовні дизайнери переходять на випадкове хешування. У випадковому хешуванні значення хеша рядка "a" може змінюватися щоразу, коли ви запускаєте програму. Випадкове хешування тепер за замовчуванням у Python (на версію 3.3), Ruby (на версію 1.9) та Perl (на версію 5.18).

Чи розумієте ви, що ви використовуєте випадкове хешування? )

Перейдіть до готовності, а не негайно, оскільки навіть дозвіл був спірним в дискусії про рефлектор

випуску 2291. std :: хеш вразливий для зіткнення DoS-атаки )

На практиці, наскільки я розумію, жодна реалізація не std::hashреалізує випадкового хешування, але ви можете написати своє my::secure_hash.

цієї відповіді )


PS

Я просто гугл "Дош хеш-таблиці" і знайшов інформативну сторінку: Момент, коли ти усвідомлюєш, що кожен сервер у світі вразливий .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.