使用像这样的MD5哈希的子字符串是否足够独特?

时间:2010-02-14 04:03:36

标签: php md5 uniqueidentifier

我要做的是为我网站上的文章创建一个12个字符的ID,类似于youtube处理其视频ID(http://www.youtube.com/watch?v=53iddd5IcSU)的方式。现在我正在生成一个MD5哈希,然后抓住它的12个字符:

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

其中$ currentID是数据库中的数字ID(例如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函数将找到唯一的id ...

4 个答案:

答案 0 :(得分:6)

使用顺序ID有什么问题?数据库将为您处理此事。

除此之外,12个字符仍然是96位。 2 96 = 79228162514264337593543950336可能的哈希值。尽管已知MD5存在碰撞漏洞,但碰撞的可能性与实际看到碰撞的概率之间存在差异。

更新

根据您正在使用的PHP md5函数的返回值,我上面的数字不太正确。

  

将哈希值作为32个字符的十六进制数返回。

由于您从32个字符的十六进制数字中取12个字符(而不是128位散列的12个字节),因此您可能最终得到的实际哈希数为16 12 = 281474976710656.还有不少。

答案 1 :(得分:1)

<?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;
  }
?>

在base-36中返回一个12个字符的数字,它给出了4,738,381,338,321,616,896种可能性。 (碰撞概率取决于随机数发生器的分布。)

为确保不发生碰撞,您需要循环:

<?php
do {
  $id = get_id();
} while ( !update_id($id) );
?>

答案 2 :(得分:0)

不是非常独特。

为什么不对base64进行编码,如果你需要它更短?

答案 3 :(得分:0)