2017-04-17 231 views
0

我已經編寫我自己的實現產生36字符的長度標識,你可以說我自己的UUID,它應該像下面的減少時間戳長度在PHP中:與填充使用哈希

  1. 當前時間戳值 - 直到長度11
  2. 隨機
  3. 4個字符大寫,小寫和數字的字符,隨後 -
  4. 隨機
  5. 20個字符大寫,小寫和數字字符

甲因此,處理該ID的數據庫表字段將在bin歸類中使其值區分大小寫。

結果ID可以是像以下示例:

1491681481-TI5b-7aCPMLK9a7MMLoSdhr5d 

這裏,時間戳長度10,我想減少其長度,並與-取代的差異。我曾嘗試搜索可用可用散列算法在PHP中:

foreach(hash_algos() as $alg){ 
     $h = hash($alg,1491681054); 
     echo $alg."==>".$h."== Length ". strlen($h)."\n<br>"; 
    } 

我發現有一些算法返回8字符長度如

  1. 的Adler32
  2. CRC32
  3. crc32b
  4. fnv132
  5. fnv1a32

那些哈希算法對我來說很好。但是,我害怕碰撞。

我需要知道這些算法的碰撞概率其中源字符串只是十進制數?換句話說,輸入類型或格式化是否應該降低這些算法中的任何一個的碰撞概率?

+0

因爲時間戳將是一個已知的因素,在代碼測試的碰撞不會採取太多的工作 – nogad

+0

@nogad你是什麼意思?但是,我並不是在談論生成的整個ID,在這個話題中,我只是指散列時間戳值。 – SaidbakR

+0

@SaidbakR我們在這裏談論什麼樣的流量?除非幾乎同時有數百/數千個請求發生,否則您必須將其分解到最接近的毫秒。如果這也是與數據庫相關的,那麼你可以使用另一種方法。 –

回答

1

maraca評論,我做了一個簡單的實現,時間戳的十進制值轉換爲基於62即數字的總和數字,大小寫英文字母的小寫如下:

<?php 

$stem = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 

$old = 10; //original base -decimal- 
$new = strlen($stem); //new base 
$num = 1491681054; // decimal input 
$out = ''; 
while($num > 0){ 
    $devide = $num/$new ;  
    $result = explode('.',$devide)[0]// could use floor();  
    $remind = $devide - $result;  
    $num = $result; 
    $out = substr($stem,round($remind * $new),1).$out; 
} 

echo "<hr>"; 
echo $out; 
// returns 1CWWnQ 

通過這種方式將長度爲10的十進制數字轉換爲長度爲6個字符的基數62。 更改爲字母字符順序,可能會導致更改輸出結果,我們也可以通過添加更多符號來增加基數。 (但要潔具如果ID將在URL中使用)

Reference