Php 比散列用户id更短的GUID?

Php 比散列用户id更短的GUID?,php,guid,user-management,Php,Guid,User Management,我想知道Instapaper(保存文本的bookmarklet)如何为他们的bookmarklet生成URL Mine的脚本src类似于www.instapaper.com/j/AnJHrfoDTRia 这些URL的质量是,它们永远不会发生冲突,并且不可能真正被猜测(因此其他人无法保存到您的帐户) 我知道一个简单的方法可能是MD5他们的电子邮件地址(假定在注册时已经检查了唯一性),但我最终会得到一个超长字符串。这不是一个大问题,但我想知道对于较短的guid,有哪些技术不会经常发生冲突(这显然是一

我想知道Instapaper(保存文本的bookmarklet)如何为他们的bookmarklet生成URL

Mine的脚本src类似于
www.instapaper.com/j/AnJHrfoDTRia

这些URL的质量是,它们永远不会发生冲突,并且不可能真正被猜测(因此其他人无法保存到您的帐户)


我知道一个简单的方法可能是MD5他们的电子邮件地址(假定在注册时已经检查了唯一性),但我最终会得到一个超长字符串。这不是一个大问题,但我想知道对于较短的guid,有哪些技术不会经常发生冲突(这显然是一种折衷,但我认为上面的12个字符非常短)

MD5用户名。获取结果MD5哈希的前X个字符。检查数据库中是否已经存在具有该值的url标记。如果是这样,请使用前X+1个字符并尝试(依此类推)。如果没有,那么您就拥有该用户的令牌。将令牌存储在DB中并从现在开始在那里查找-不要每次都尝试从用户名或诸如此类的内容重新创建令牌

您可以从X=7开始,做得很好(对于绝大多数令牌代,尝试次数不超过1-2次)


此外,您可能希望在散列计算中添加其他内容(例如,他们的或随机数),以便更难预测给定用户的令牌。

MD5用户名。获取结果MD5哈希的前X个字符。检查数据库中是否已经存在具有该值的url标记。如果是这样,请使用前X+1个字符并尝试(依此类推)。如果没有,那么您就拥有该用户的令牌。将令牌存储在DB中并从现在开始在那里查找-不要每次都尝试从用户名或诸如此类的内容重新创建令牌

您可以从X=7开始,做得很好(对于绝大多数令牌代,尝试次数不超过1-2次)


此外,您可能希望在散列计算中添加其他内容(例如,它们的或随机数),以便更难预测给定用户的令牌。

您可以通过将MD5散列视为基数为16的数字(使用字符(0-9a-f)并将其转换为例如基数36来获得较短的字符串

<?php
function gmp_convert($num, $base_a, $base_b) {
    return gmp_strval (gmp_init($num, $base_a), $base_b );
}

$hash = md5("hello");
$hash2 = gmp_convert($hash,16,36);
echo "$hash <br>"; //5d41402abc4b2a76b9719d911017c592 
echo $hash2; //5ir3t0ozoelrnauhrwyu1xfgy

您可以通过将MD5哈希处理为以16为基数的数字(使用字符(0-9a-f))并将其转换为例如以36为基数的数字来获得较短的字符串

<?php
function gmp_convert($num, $base_a, $base_b) {
    return gmp_strval (gmp_init($num, $base_a), $base_b );
}

$hash = md5("hello");
$hash2 = gmp_convert($hash,16,36);
echo "$hash <br>"; //5d41402abc4b2a76b9719d911017c592 
echo $hash2; //5ir3t0ozoelrnauhrwyu1xfgy
对一组加密的强随机数进行编码

<?php
// get 72 pseudorandom bits in a base64 string of 12 characters

$pr_bits = '';

// Unix/Linux platform?
$fp = @fopen('/dev/urandom','rb');
if ($fp !== FALSE) {
    $pr_bits .= @fread($fp,9);
    @fclose($fp);
}

// MS-Windows platform?
if (@class_exists('COM')) {
    // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
    try {
        $CAPI_Util = new COM('CAPICOM.Utilities.1');
        $pr_bits .= $CAPI_Util->GetRandom(9,0);

        // if we ask for binary data PHP munges it, so we
        // request base64 return value.  We squeeze out the
        // redundancy and useless ==CRLF by hashing...
        if ($pr_bits) { $pr_bits = substr(md5($pr_bits,TRUE), 0, 9); }
    } catch (Exception $ex) {
        // echo 'Exception: ' . $ex->getMessage();
    }
}

$uid = base64_encode($pr_bits);
?>

这将在12个字符中为您提供72位最纯净的哥伦布数字。这组数字大约包含10^21个数字。这意味着100万用户之后发生冲突的几率约为十亿分之一

这是对这个stackoverflow答案的一个非常细微的修改,用于生成加密的惊人效果:。

对一组加密的强随机数进行编码

<?php
// get 72 pseudorandom bits in a base64 string of 12 characters

$pr_bits = '';

// Unix/Linux platform?
$fp = @fopen('/dev/urandom','rb');
if ($fp !== FALSE) {
    $pr_bits .= @fread($fp,9);
    @fclose($fp);
}

// MS-Windows platform?
if (@class_exists('COM')) {
    // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
    try {
        $CAPI_Util = new COM('CAPICOM.Utilities.1');
        $pr_bits .= $CAPI_Util->GetRandom(9,0);

        // if we ask for binary data PHP munges it, so we
        // request base64 return value.  We squeeze out the
        // redundancy and useless ==CRLF by hashing...
        if ($pr_bits) { $pr_bits = substr(md5($pr_bits,TRUE), 0, 9); }
    } catch (Exception $ex) {
        // echo 'Exception: ' . $ex->getMessage();
    }
}

$uid = base64_encode($pr_bits);
?>

这将在12个字符中为您提供72位最纯净的哥伦布数字。这组数字大约包含10^21个数字。这意味着100万用户之后发生冲突的几率约为十亿分之一


这是对这个stackoverflow答案的一个非常细微的修改,用于生成密码的惊人效果:。

如果某个时间它将是
+1 char
(它意味着可预测的),那么有什么理由使用
md5(微时间(1))
md5(uniqid())呢
?@zerkms:所有完全可以接受的选项。您甚至可以只使用
md5(rand())
。此外,为了增加容量,最好不要使用md5,而只是从0-9a-zA-Z随机生成字符。它将为我们提供322626676239789821056个独特的组合,而md5的组合是281474976710656(比md5大1100万倍)虽然一旦你超过了百万/十亿大关,这并不总是重要的。@Amber:但它可以使哈希值更短:1048576(显然是不够的)vs 916132832只需要5个字符。即使是4个字符:65536对14776336,第二个字符满足了我们的欲望,而第一个字符很糟糕。有没有理由使用
name
md5
+1个字符
的话(这意味着可以预测)?为什么不干脆
md5(microtime(1))
md5(uniqid())
?@zerkms:所有完全可以接受的选项。您甚至可以只使用
md5(rand())
。此外,为了增加容量,最好不要使用md5,而只是从0-9a-zA-Z随机生成字符。它将为我们提供322626676239789821056个独特的组合,而md5的组合是281474976710656(比md5大1100万倍)虽然一旦你超过百万/十亿大关,这并不总是重要的。@Amber:但它允许将哈希值缩短很多:1048576(显然是不够的)比916132832只需5个字符。即使是4个字符:65536比14776336,第二个满足我们的要求,而第一个则很糟糕。如果你的数据库中有带(自动递增)的条目整数ID已存在,仅用于获取它们所拥有的内容。这是完全无冲突的,但已模糊且简短。如果数据库中的条目已具有(自动递增)整数ID,则仅使用获取它们所拥有的内容。这是完全无冲突的,但已模糊且简短。