2011-01-11 23 views
1

我想知道Instapaper(保存文本的小書籤)如何爲其書籤生成URL。比散列用戶ID更短的GUID?

煤礦有類似的腳本SRC給www.instapaper.com/j/AnJHrfoDTRia

這些URL的質量,他們需要從來沒有發生碰撞,並沒有真的被猜到的(所以其他人無法保存到您的帳戶)。

我知道一個簡單的方法可能是MD5他們的電子郵件地址(假設已經檢查註冊的唯一性),但是我最終會得到一個超長的字符串。這不是一個很大的問題,但我想知道什麼技術有較短的GUID,不會經常碰撞(這顯然是折衷,但在我看來,上面的12個字符非常短)

回答

-2

MD5用戶名。獲取生成的MD5哈希的前X個字符。檢查數據庫中是否存在具有該值的url標記。如果是這樣,取第一個X + 1字符並嘗試(等等)。如果沒有,那麼你有該用戶的令牌。將令牌存儲在數據庫中,並從現在開始查看 - 不要每次都嘗試從用戶名重新創建令牌或不使用該令牌。

你可以從X = 7開始並且做的很好(對於絕大多數代數生成不超過1-2次嘗試)。另外,您可能希望在散列計算中添加其他內容(比如說,它們或一個隨機數),以便更難預測給定用戶的令牌。

+1

某些時候使用'name'的`md5`的任何理由,如果它是'+1 char'(這意味着**可預測的**)?爲什麼不只是`md5(microtime(1))`或`md5(uniqid())`? – zerkms 2011-01-11 04:14:55

2

可以通過在底座16處理MD5哈希作爲數得到一個較短的字符串(即使用字符(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 

鏈路你提到好像是用所有的字母(大小寫)。

信息從these Q&As

0
<?php 

$length = 12; 

$chars = array_merge(range(0, 9), range('a', 'z'), range('A', 'Z')); 

$hash = ''; 

for ($i = 0; $i < $length; $i++) { 
    $hash .= $chars[array_rand($chars)]; 
} 

var_dump($hash); 

提取這將使我們3226266762397899821056獨特對於md5(這是大1100萬倍)的組合vs 281474976710656。

只需4個字符(!),它將是14776336個獨特的組合,它可以滿足您的需求。

0

Base64對密碼強的一組隨機數進行編碼。

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

這會給你72位最純淨的哥倫比亞人,12個字符。這個集合包含大約10^21個數字。這意味着在100萬用戶之後發生碰撞的可能性大約爲十億分之一。

這是一個非常輕微修改這個生成crypto awesomeness的stackoverflow答案:Secure random number generation in PHP