Почему MD5's UUID не очень хорошая идея?

PHP имеет функцию uniqid (), которая генерирует UUID.

В примерах использования он показывает следующее:

$token = md5(uniqid());

Но в комментариях кто-то говорит это :

Генерация MD5 из уникального идентификатора наивна и снижает значительную часть уникальных идентификаторов, а также обеспечивает значительную (атакующую) стриктуру в домене MD5. Это глубоко сломанная вещь. Правильный подход – использовать уникальный идентификатор самостоятельно; он уже предназначен для не столкновений.

Почему это так, если так? Если хеш MD5 (почти) уникален для уникального идентификатора, то что не так из md5's uniqid?

UUID имеет ширину 128 бит и обладает уникальностью, присущей способу его генерации. Хэш MD5 имеет ширину 128 бит и не гарантирует уникальность, только низкую вероятность столкновения. Хэш MD5 не меньше UUID, поэтому он не помогает при хранении.

Если вы знаете, что хеш из UUID, гораздо легче атаковать, потому что домен действительных UUID на самом деле достаточно предсказуем, если вы знаете что-нибудь о машине, производящей их.

Если вам нужно предоставить безопасный токен, вам нужно будет использовать криптографически безопасный генератор случайных чисел. (1) UUID не предназначены для криптографической защиты, только гарантированы уникальными. Монотонно возрастающая последовательность, ограниченная уникальными идентификаторами машины (обычно MAC) и временем, по-прежнему является вполне допустимым UUID, но очень предсказуемым, если вы можете перепроектировать один UUID из последовательности токенов.

  1. Определяющей характеристикой криптографически защищенного PRNG является то, что результат данной итерации не содержит достаточной информации, чтобы вывести значение следующей итерации – т. Е. В генераторе есть какое-то скрытое состояние, которое не отображается в номере и не может быть выведено путем изучения последовательности чисел из PRNG.

    Если вы переходите к теории чисел, вы можете найти способы угадать внутреннее состояние некоторых PRNG из последовательности генерируемых значений. Пример такого генератора – Мерсенн Твистер . У этого есть скрытое состояние, которое оно использовало, чтобы получить его длинный период, но это не криптографически безопасно – вы можете взять довольно небольшую последовательность чисел и использовать это, чтобы вывести внутреннее состояние. Как только вы это сделаете, вы можете использовать его для атаки криптографического механизма, который зависит от сохранения этой последовательности в секрете.

Обратите внимание, что uniqid() не возвращает UUID , а уникальную строку, основанную на текущем времени:

 $ php -r 'echo uniqid("prefix_", true);' prefix_4a8aaada61b0f0.86531181 

Если вы сделаете это несколько раз, вы получите очень похожие выходные строки, и все, кто знаком с uniqid() , распознают исходный алгоритм. Таким образом, довольно легко предсказать следующие идентификаторы, которые будут сгенерированы.

Преимущество вывода md5 (), а также солевой строки приложения или случайного числа – путь, который сложнее угадать:

 $ php -r 'echo md5(uniqid("prefix_", true));' 3dbb5221b203888fc0f41f5ef960f51b 

В отличие от простого uniqid() , это дает очень разные выходы каждые микросекунды. Кроме того, он не содержит вашу строку «префикс соли», а также то, что вы используете uniqid() под капотом. Не зная соль, это очень сложно (считают невозможным) угадать следующий идентификатор.

В заключение я бы не согласился с мнением комментатора и всегда предпочел вывод md5() поверх простого uniqid() .

MD5ing UUID бессмысленен, поскольку UUID уже уникальны и фиксированы (короткие), свойства, которые являются некоторыми из причин, по которым люди часто используют MD5 для начала. Поэтому я полагаю, что это зависит от того, что вы планируете делать с UUID, но в целом UUID имеет те же свойства, что и некоторые данные, которые были MD5'd, так почему же оба?

UUID уже уникальны, поэтому в MD5 их нет смысла.

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

Это особенно верно, если злоумышленник может получить от вас целую кучу уникальных идентификаторов, и таким образом угадать вашу схему генерации UUID.

Версия 3 UUID уже MD5'd, поэтому нет смысла делать это снова. Тем не менее, я не уверен, что использует версия UUID PHP.

В стороне MD5 фактически устарел и не должен использоваться ни в чем, что стоит защитить – PHI, PII или PCI – с 2010 года. Федеральные власти США укрепили это, и любое юридическое лицо, не отвечающее требованиям, будет выплачивать штраф в размере $$$.