Remove ads
З Вікіпедії, вільної енциклопедії
Хеш-фу́нкція[1], або геш-фу́нкція[2][3] — функція, що перетворює вхідні дані будь-якого (як правило великого) розміру в дані фіксованого розміру.
Хешування (гешування, англ. hashing) — перетворення вхідного масиву даних довільної довжини у вихідний бітовий рядок фіксованої довжини. Такі перетворення також називаються хеш-функціями, або функціями згортання, а їхні результати називають хешем, хеш-кодом, хеш-сумою, або дайджестом повідомлення (англ. message digest).
Хеш-функція використовується зокрема у структурах даних — хеш-таблицях, широко вживаних у програмному забезпеченні для швидкого пошуку даних. Хеш-функції використовуються для оптимізації таблиць та баз даних користуючись з того, що в однакових записів однакові значення хеш-функції. Такий підхід пошуку дублікатів ефективний у файлах великого розміру. Прикладом цього буде знаходження подібних ділянок у послідовностях ДНК. Криптографічна геш-функція дозволяє легко перевірити, що деякі вхідні дані зіставляються із заданим значенням хешу, але, якщо вхідні дані невідомі, то навмисно важко відновити вхідне значення (або еквівалентну альтернативу), знаючи збережене значення хеш-функції. Це використовується для забезпечення цілісності переданих даних, і є будівельним блоком для HMACs, які забезпечують аутентифікацію повідомлень.
Хеш-функції пов'язані (і їх часто плутають) з контрольною сумою, контрольними цифрами, відбитками пальців, рандомізацією функцій, кодами, що виправляють помилки, і з шифрами. Хоча ці поняття певною мірою збігаються, кожне з них має свою власну сферу застосування і вимоги та є розробленим і оптимізованим по-різному.
Дональд Кнут приписує першу систематичну ідею гешування співробітнику IBM Ханса Петера Луна[en], який запропонував геш-кодування у січні 1953 року.
У 1956 році Арнольд Думи[en] у своїй роботі «Computers and automation» першим представив концепцію гешування такою, якою її знає більшість програмістів у наш час. Думи розглядав гешування, як рішення «Проблеми словника», а також запропонував використовувати як геш-адресу залишок від ділення на просте число.[4]
Першою значною роботою, яка була пов'язана з пошуком у великих файлах, була стаття Уеслі Пітерсона[en] в IBM Journal of Research and Development 1957 року, в якій він визначив відкриту адресацію, а також вказав на погіршення продуктивності при видаленні. Через шість років була опублікована робота Вернера Бухгольца[de], у якій в значній мірі досліджувалися хеш-функції. Протягом кількох наступних років гешування широко використовувалося, однак не було опубліковано жодної значної роботи.
У 1967 році гешування в сучасному значенні згадано в книзі Херберта Хеллерман «Принципи цифрових обчислювальних систем»[5]. У 1968 році Роберт Морріс[en] опублікував у Communications of the ACM великий огляд про гешування. Ця робота вважається публікацією, що вводить поняття про гешуванні в науковий обіг і остаточно закріпляє серед фахівців термін «геш».
До початку 1990-х років еквівалентом терміну «гешування», завдяки роботам Андрія Єршова, використовувалося слово рос. «расстановка», а для колізій використовувався термін рос. «конфликт» (Єршов використовував «расстановку» з 1956, а також в російськомовному виданні книги Ніклауса Вірта «Алгоритми та структури даних» (1989) використовується цей термін). Проте жоден з цих варіантів не прижився, і в літературі використовується переважно термін «гешування».[6]
Хешування застосовується для побудови асоціативних масивів, пошуку дублікатів в серіях наборів даних, побудови унікальних ідентифікаторів для наборів даних, контрольного підсумовування з метою виявлення випадкових або навмисних помилок при зберіганні або передачі, для зберігання паролів в системах захисту (у цьому випадку доступ до області пам'яті, де знаходяться паролі, не дозволяє відновити сам пароль), при виробленні електронного підпису (на практиці часто підписується не саме повідомлення, а його геш-образ).
У загальному випадку однозначної відповідності між вихідними даними і геш-кодом немає в силу того, що кількість значень геш-функцій менша, ніж число варіантів значень вхідного масиву. Існує безліч масивів з різним вмістом, що дають однакові геш-коди — так звані колізії. Імовірність виникнення колізій відіграє важливу роль в оцінці якості геш-функцій.
Розроблено багато алгоритмів гешування з різними властивостями (розрядність, обчислювальна складність, криптостійкість тощо). Вибір тієї чи іншої геш-функції визначається специфікою розв'язуваної задачі. Найпростішими прикладами геш-функцій можуть служити контрольна сума або CRC.
Хороша геш-функція повинна задовольняти двом властивостям:
Припустимо, для визначеності, що — кількість ключів, а геш-функція має не більше різних значень:
Як приклад «поганої» геш-функції можна навести функцію з , яка десятизначному натуральному числу співставляє три цифри, обрані з середини двадцятизначного квадрата числа . Здавалося б, значення геш-кодів повинні рівномірно розподілитися між «000» і «999», але для реальних даних такий метод підходить лише у тому випадку, якщо ключі не мають великої кількості нулів зліва чи справа. [6]
Однак, існує декілька інших простих та надійних методів, на яких базується багато геш-функцій.
Перший метод полягає у тому, що ми використовуємо як геш — залишок від ділення на , де — це кількість всіх можливих гешів:
При цьому очевидно, що при парному значення функції буде парним, при парному . А непарним — при непарному, що може призвести до значного зсуву даних в файлах. Також не слід використовувати як базу системи числення комп'ютера, оскільки геш-код буде залежати тільки від кількох цифр числа , розташованих праворуч, що призведе до великої кількості колізій. На практиці зазвичай обирають просте — в більшості випадків цей вибір цілком задовільний.
Ще слід сказати про метод гешування, в основі якого полягає ділення на поліном по модулю два. У даному методі також повинна бути ступенем двійки, а бінарні ключі () мають вигляд поліномів. У цьому випадку як геш-код беруться значення коефіцієнтів полінома, отриманого як залишок від ділення на заздалегідь обраний поліном ступеня :
При правильному виборі такий спосіб гарантує відсутність колізій між майже однаковими ключами. [6]
Другий метод полягає у виборі деякої цілої константи , взаємно простої з , де — кількість можливих варіантів значень у вигляді машинного слова (в комп'ютерах IBM PC ). Тоді маємо змогу взяти геш-функцію виду:
У цьому випадку, на комп'ютері з двійковою системою числення, являє собою ступінь двійки, а складатиметься зі старших бітів правої половини добутку .
Серед переваг цих двох методів варто відзначити, що вони вигідно використовують те, що реальні ключі невипадкові. Наприклад, у тому випадку, якщо ключі являють собою арифметичну прогресію (припустимо послідовність назв «ім'я1», «ім'я2», «ім'я3»). Мультиплікативний метод відобразить арифметичну прогресію у наближену арифметичну прогресію різних геш-значень, що зменшує кількість колізій у порівнянні з випадковою ситуацією.
Однією з варіацій даного методу є гешування Фібоначчі, засноване на властивостях золотого перетину. Як тут обирається найближче до ціле число, взаємно просте з
Вищевикладені методи застосовуються і в тому випадку, коли нам необхідно розглядати ключі, що складаються з декількох слів або ключі зі змінною довжиною. Наприклад, можна скомбінувати слова в одне за допомогою додавання за модулем або операції «додавання по модулю 2». Одним з алгоритмів, що працюють за таким принципом, є геш-функція Пірсона.
Гешування Пірсона[en] — алгоритм, запропонований Пітером Пірсоном (англ. Peter Pearson) для процесорів з 8-бітними регістрами, завданням якого є швидке обчислення геш-коду для рядка довільної довжини. На вхід функція отримує слово , що складається з символів, кожен розміром 1 байт, і повертає значення в діапазоні від 0 до 255. При цьому значення геш-коду залежить від кожного символу вхідного слова.
Алгоритм можна описати таким псевдокодом, який отримує на вхід рядок і використовує таблицю перестановок
h := 0
For each c in W loop
index := h xor c
h := T [index]
End loop'
Return h
Серед переваг алгоритму слід зазначити:
Як альтернативний спосіб гешування ключів, котрі складаються з символів (), можна запропонувати обчислення
Геш-функції широко використовуються в криптографії, а також у багатьох структурах даних — Геш-таблицях, фільтрах Блума і декартових деревах.
Серед великої кількості геш-функцій прийнято виділяти криптографічно стійкі, застосовувані в криптографії, оскільки на них накладаються додаткові вимоги. Для того, щоб геш-функція вважалася криптографічно стійкою, вона повинна задовільняти трьом основним вимогам, на яких засновано більшість застосувань геш-функцій в криптографії:
Дані вимоги залежні один від одного:
Слід зазначити, що не доведене існування незворотних геш-функцій, для яких обчислення будь-якого прообразу заданого значення геш-функції теоретично неможливо. Зазвичай знаходження зворотного значення є лише обчислювально складним завданням.
Атака «днів народження» дозволяє знаходити колізії для геш-функції з довжиною значень n бітів в середньому за приблизно обчислень геш-функції. Тому n -бітна геш-функція вважається крипостійкою, якщо обчислювальна складність знаходження колізій для неї близька до .
Для криптографічних геш-функцій також важливо, щоб при щонайменшій зміні аргументу значення функції сильно змінювалося (лавинний ефект). Зокрема, значення гешу не повинно давати витоку інформації, навіть про окремі біти аргументу. Ця вимога є запорукою криптостійкості алгоритмів гешування, гешуючих пароль користувача для отримання ключа. [7]
Гешування часто використовується в алгоритмах електронно-цифрового підпису, де шифрується не саме повідомлення, а його геш-код, що зменшує час обчислення, а також підвищує криптостійкість. Також в більшості випадків, замість паролів зберігаються значення їх геш-кодів.
Геометричне гешування (англ. Geometric hashing) — широко застосовуваний у комп'ютерній графіці й обчислювальній геометрії метод для вирішення завдань на площині або в тривимірному просторі, наприклад, для знаходження найближчих пар в множині точок або для пошуку однакових зображень. Геш-функція в даному методі зазвичай отримує на вхід якийсь метричний простір і розділяє його, створюючи сітку з клітин. Таблиця у цьому випадку є масивом з двома або більше індексами і має назву файл сітки (англ. Grid file). Геометричне гешування також застосовується в телекомунікаціях при роботі з багатовимірними сигналами.
Геш-таблиця — це структура даних, що дозволяє зберігати пари виду (ключ, геш-код) і підтримує операції пошуку, вставки та видалення елементів. Завданням геш-таблиць є прискорення пошуку, наприклад, у випадку записів до текстових полів в базі даних може розраховуватися їх геш код і дані можуть поміщатися у розділ, що відповідає цьому геш-коду. Тоді при пошуку даних треба буде спочатку обчислити геш-код тексту і відразу стане відомо, в якому розділі їх треба шукати, тобто, шукати треба буде не по всій базі, а тільки по одному її розділу (це сильно прискорює пошук).
Побутовим аналогом гешування у цьому випадку може служити розміщення слів у словнику за алфавітом. Перша літера слова є його геш-кодом, і при пошуку ми переглядаємо не весь словник, а тільки потрібну літеру.
Деякі алгоритми гешування
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.