Будет ли использование подстроки хеша MD5, подобного этому, достаточно уникальным? - PullRequest
8 голосов
/ 14 февраля 2010

Я пытаюсь создать 12-символьный идентификатор для статей на моем веб-сайте, аналогично тому, как YouTube обрабатывает их видео-идентификатор (http://www.youtube.com/watch?v=53iddd5IcSU).). Сейчас я генерирую хэш MD5, а затем собираю 12 символов как это:

$ArticleId = substr(MD5("Article".$currentID),10,12)

где $ currentID - числовой идентификатор из базы данных (например, 144)

Я немного параноик, что столкнусь с дубликатом $ ArticleId, но реалистично, каковы шансы, что это произойдет? А также, учитывая, что столбец в моей базе данных является уникальным, как я могу справиться с этим редким сценарием без появления ужасной ошибки?

P.S. Я сделал небольшой скрипт для проверки дубликатов в первых 5000 $ ArticleId, но их не было.

РЕДАКТИРОВАТЬ: мне не нравится, как выглядят хеши base64_encode, поэтому я сделал это:

function retryAID($currentID)
{
    $AID = substr(MD5("Article".$currentID*2),10,12);

    $setAID = "UPDATE `table` SET  `artID` =  '$AID' WHERE `id` = $currentID ";
    mysql_query($setLID) or retryAID($currentID);
}


$AID = substr(MD5("Article".$currentID),10,12);

$setAID = "UPDATE `table` SET  `artID` =  '$AID' WHERE `id` = $currentID ";
mysql_query($setAID) or retryAID($currentID);

Поскольку столбец AID уникален, mysql_query выдаст ошибку, а функция retryAID найдет уникальный идентификатор ...

Ответы [ 4 ]

6 голосов
/ 14 февраля 2010

Что не так с использованием последовательного идентификатора? База данных будет обрабатывать это для вас.

Кроме того, 12 символов по-прежнему 96 бит. 2 96 = 79228162514264337593543950336 возможных хэшей. Несмотря на то, что MD5, как известно, имеет уязвимости при столкновении, существует огромная разница между вероятностью столкновения и вероятностью ее фактического просмотра.

Обновление:

Исходя из возвращаемого значения используемой вами функции PHP md5 , приведенные выше цифры не совсем верны.

Возвращает хеш в виде 32-значного шестнадцатеричного числа.

Поскольку вы берете 12 символов из шестнадцатеричного числа из 32 символов (а не 12 байтов 128-битного хэша), фактическое количество возможных хэшей, которое вы можете получить, составляет 16 12 = 281474976710656. Еще немало.

1 голос
/ 14 февраля 2010
<?php
  function get_id()
  {
    $max = 1679615; // pow(36, 4) - 1;
    $id = '';

    for ($i = 0; $i < 3; ++$i)
    {
      $r = mt_rand(0, $max);
      $id .= str_pad(base_convert($r, 10, 36), 4, "0", STR_PAD_LEFT);
    }
    return $id;
  }
?>

Возвращает 12-значное число в base-36, что дает 4 738 381 338 321 616 896 возможностей. (Вероятность столкновения зависит от распределения генератора случайных чисел.)

Чтобы избежать коллизий, вам нужно выполнить цикл:

<?php
do {
  $id = get_id();
} while ( !update_id($id) );
?>
0 голосов
/ 14 февраля 2010
0 голосов
/ 14 февраля 2010

Нет, не очень уникальный.

Почему бы base64 не закодировать его, если он вам нужен короче?

...