Подтвердить что ты не робот

Md5 (uniqid) имеет смысл для случайных уникальных токенов?

Я хочу создать генератор токенов, который генерирует токены, которые не могут быть угаданы пользователем и которые по-прежнему уникальны (используется для сброса пароля и кодов подтверждения).

Я часто вижу этот код; это имеет смысл?

md5(uniqid(rand(), true));

Согласно комментарий uniqid($prefix, $moreEntopy = true) дает

первые 8 шестнадцатеричных символов = Unixtime, последние 5 шестнадцатеричных символов = микросекунды.

Я не знаю, как обрабатывается $prefix -параметр.

Итак, если вы не устанавливаете флаг $moreEntopy в значение true, он дает прогнозируемый результат.


ВОПРОС: Но если мы используем uniqid с $moreEntopy, что хеширует его при покупке md5? Это лучше, чем:

md5(mt_rand())

edit1: Я буду хранить этот токен в столбце базы данных с уникальным индексом, поэтому я буду определять столбцы. Может представлять интерес/

4b9b3361

Ответ 1

rand() является угрозой безопасности и никогда не должен использоваться для создания маркера безопасности: rand() vs mt_rand() (Look на "статических" изображениях). Но ни один из этих методов генерации случайных чисел не криптографически защищен. Для создания защищенных приложений приложение должно получить доступ к CSPRNG, предоставляемому платформой, операционной системой или аппаратным модулем.

В веб-приложении хорошим источником безопасных секретов является неблокирующий доступ к энтропийному пулу, например /dev/urandom. Начиная с PHP 5.3, приложения PHP могут использовать openssl_random_pseudo_bytes(), а библиотека Openssl выберет лучший источник энтропии на основе вашей операционной системы, в Linux это означает, что приложение будет использовать /dev/urandom. Этот код от Скотта довольно хорош:

function crypto_rand_secure($min, $max) {
        $range = $max - $min;
        if ($range < 0) return $min; // not so random...
        $log = log($range, 2);
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd >= $range);
        return $min + $rnd;
}

function getToken($length=32){
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    for($i=0;$i<$length;$i++){
        $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];
    }
    return $token;
}

Ответ 2

Это копия другого вопроса, который я нашел, который был задан за несколько месяцев до этого. Вот ссылка на вопрос и мой ответ: fooobar.com/questions/25795/....

Я не согласен с принятым ответом. Согласно веб-сайту PHP "[uniqid] does not generate cryptographically secure tokens, in fact without being passed any additional parameters the return value is little different from microtime(). If you need to generate cryptographically secure tokens use openssl_random_pseudo_bytes()."

Я не думаю, что ответ может быть более ясным, чем это, uniqid не является безопасным.

Ответ 3

Я знаю, что вопрос старый, но он появляется в Google, поэтому...

Как говорили другие, rand(), mt_rand() или uniqid() не гарантируют вам уникальности... даже openssl_random_pseudo_bytes() не следует использовать, поскольку он использует устаревшие функции OpenSSL.

То, что вы должны использовать для генерации случайного хэша (то же, что и md5), random_bytes() (представлено в PHP7). Чтобы генерировать хэш с такой же длиной, как MD5:

bin2hex(random_bytes(16));

Если вы используете PHP 5.x, вы можете получить эту функцию, включив random_compat library.

Ответ 4

Определите "уникальный". Если вы имеете в виду, что два токена не могут иметь одинаковое значение, то хеширования недостаточно - его нужно поддерживать с помощью теста уникальности. Тот факт, что вы поставляете хэш-алгоритм с уникальными входами, не гарантирует уникальные выходы.

Ответ 5

Чтобы ответить на ваш вопрос, проблема в том, что у вас не может быть генератора, который гарантирован случайным и уникальным, как случайный сам по себе, т.е. md5(mt_rand()) может привести к дублированию. То, что вам нужно, это "случайные появления" уникальных значений. uniqid дает уникальный id, rand() прикрепляет случайное число, что делает его еще труднее догадаться, md5 маскирует результат, чтобы сделать его еще сложнее угадать. Ничего нет. Нам просто нужно сделать так, чтобы они даже не захотели попробовать.

Ответ 6

Несколько лет назад я столкнулся с интересной идеей.
Сохранение двух значений хеширования в дате, один из которых генерируется с помощью md5 ($ a), а другой - с помощью sha ($ a). Затем произнесите chek, если оба значения являются corect. Точка, если злоумышленник сломал ваш md5(), он не может сломать ваш md5 и sha в ближайшем будущем.
Проблема заключается в следующем: как можно использовать эту концепцию для генерации маркера, необходимой для вашей проблемы?

Ответ 7

MD5 - достойный алгоритм для создания зависимых от данных идентификаторов. Но в случае, если у вас есть более одного элемента, который имеет один и тот же бит-поток (контент), вы будете создавать два похожих MD5-идентификатора.

Итак, если вы просто применяете его к функции rand(), которая гарантированно не будет создавать один и тот же номер дважды, вы совершенно безопасны.

Но для более сильного распределения ключей я лично использовал SHA1 или SHAx и т.д.... но у вас все еще будет проблема с подобными данными, приводящими к аналогичным клавишам.