2017-04-17 137 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