Попри те , що самі upvoted відповідей тут підкреслити, то , НЕ приемистости (тобто що є кілька рядків хешування до того ж значенням) криптографічного хеш - функції , викликаної різницею між великим (потенційно нескінченним) розміром вхідного і фіксованого розміром вихідного НЕ важливий момент - насправді, ми віддаємо перевагу хеш-функціям, коли ці зіткнення трапляються якомога рідше.
Розглянемо цю функцію (у позначенні PHP як запитання):
function simple_hash($input) {
return bin2hex(substr(str_pad($input, 16), 0, 16));
}
Це додає деякі пробіли, якщо рядок занадто короткий, а потім приймає перші 16 байт рядка, а потім кодує його як шістнадцяткове. Він має такий самий розмір виводу, як хеш MD5 (32 шістнадцяткові символи, або 16 байт, якщо опустити частину bin2hex).
print simple_hash("stackoverflow.com");
Це виведе:
737461636b6f766572666c6f772e636f6d
Ця функція також має ту саму властивість неін'єктивності, яку підкреслює відповідь Коді для MD5: Ми можемо передавати рядки будь-якого розміру (якщо вони поміщаються в наш комп'ютер), і вона видасть лише 32 шістнадцяткові цифри. Звичайно, це не може бути ін’єкційним.
Але в цьому випадку тривіально знайти рядок, який відповідає одному і тому ж хешу (просто застосуйте hex2bin
до свого хешу, і у вас він є). Якщо ваш початковий рядок мав довжину 16 (як наш приклад), ви навіть отримаєте цей оригінальний рядок. Нічого подібного не повинно бути можливим для MD5, навіть якщо ви знаєте, що довжина введення була досить короткою (за винятком випробування всіх можливих входів, поки ми не знайдемо такий, який відповідає, наприклад, атака грубої сили).
Важливими припущеннями для криптографічної хеш-функції є:
- важко знайти будь-який рядок, що виробляє даний хеш (опір зображення)
- важко знайти будь-який інший рядок, що виробляє той самий хеш, що і даний рядок (другий опір зображення)
- важко знайти пару рядків з однаковим хешем (стійкість до зіткнень)
Очевидно, що моя simple_hash
функція не виконує жодної з цих умов. (Насправді, якщо ми обмежимо вхідний простір "16-байтовими рядками", тоді моя функція стає ін'єктивною і, отже, навіть доказується стійкою до другої зображення та стійкою до зіткнень.)
Зараз існують атаки зіткнень проти MD5 (наприклад, можна створити пару рядків, навіть із заданим однаковим префіксом, які мають однаковий хеш, з досить великою кількістю роботи, але не неможливо багато роботи), тому вам не слід використовувати MD5 для чогось критичного. Поки ще немає атаки з зображеннями, але атаки стануть кращими.
Щоб відповісти на актуальне запитання:
Що саме в цих функціях робить результуючі рядки неможливими?
Те, що MD5 (та інші хеш-функції, побудовані на конструкції Меркле-Дамгарда) ефективно робить, це застосування алгоритму шифрування з повідомленням як ключем та деяким фіксованим значенням як "звичайний текст", використовуючи отриманий зашифрований текст як хеш. (До цього вхідні дані доповнюються і діляться на блоки, кожен із цих блоків використовується для шифрування виводу попереднього блоку, XORed з його входом для запобігання зворотним обчисленням.)
Сучасні алгоритми шифрування (включаючи ті, що використовуються в хеш-функціях) створені таким чином, щоб важко було відновити ключ, навіть з урахуванням відкритого тексту та зашифрованого тексту (або навіть коли противник вибирає один із них). Зазвичай вони роблять це, виконуючи багато операцій перетасовки бітів таким чином, що кожен вихідний біт визначається кожним ключовим бітом (кілька разів), а також кожним вхідним бітом. Таким чином, ви можете легко простежити, що відбувається всередині, лише якщо ви знаєте повну клавішу і введення, або вихід.
Для хеш-функцій, подібних до MD5, та атаки перед зображеннями (з хешованим рядком з одним блоком, щоб полегшити ситуацію), у вас є лише вхід і вихід вашої функції шифрування, але не ключ (це те, що ви шукаєте).