CakePHP中的唯一令牌


Unique token in CakePHP

在CakePHP中插入记录时,我需要创建真正唯一的令牌。这个表可以包含数百万行,所以我不能仅仅基于一些随机生成的字符串。我也不想使用microtime(),因为两条记录在同一时刻提交的可能性很小。当然,最好的解决方案是使用String::uuid(),但根据cakepp文档

uuid方法用于根据RFC 4122生成唯一标识符。uuid是一个128位字符串,格式为485fc381-e790-47a3-9794-1337c0a8fe68。

所以,据我所知,它这一代人并没有使用蛋糕的安全盐。因此,我决定通过安全组件的哈希函数(或Auth-Password函数)对其进行哈希,因为我需要它是唯一的,同时非常非常安全。但后来我发现了这个问题,说这不是一个好主意,但对于php-uniqid和md5来说。为什么MD5';使用UUID不是个好主意?

而且,我还认为安全组件散列后的字符串更难猜测,因为例如,for循环中的String::uuid()有一个类似的输出

for ($i = 0; $i < 30; $i++) {
    echo String::uuid()."<br>";
}       
die;
// outputs
51f3dcda-c4fc-4141-aaaf-1378654d2d93
51f3dcda-d9b0-4c20-8d03-1378654d2d93
51f3dcda-e7c0-4ddf-b808-1378654d2d93
51f3dcda-f508-4482-852d-1378654d2d93
51f3dcda-01ec-4f24-83b1-1378654d2d93
51f3dcda-1060-49d2-adc0-1378654d2d93
51f3dcda-1da8-4cfe-abe4-1378654d2d93
51f3dcda-2af0-42f7-81a0-1378654d2d93
51f3dcda-3838-4879-b2c9-1378654d2d93
51f3dcda-451c-465a-a644-1378654d2d93
51f3dcda-5264-44b0-a883-1378654d2d93

因此,毕竟字符串的某些部分是相似的,但在使用哈希函数的情况下,结果是非常不同的

echo Security::hash('stackoverflow1');
echo "<br>";
echo Security::hash('stackoverflow2');
die;
// outputs
e9a3fcb74b9a03c7a7ab8731053ab9fe5d2fe6bd
b1f95bdbef28db16f8d4f912391c22310ba3c2c2

所以,问题是,我到底能把Cake中的uuid()散列吗?或者,获得真正独特和散列(根据我的安全盐,更好)的安全令牌的最佳安全方式是什么。

更新

说安全代币,我的意思是猜测有多难。UUID确实是唯一的,但从上面的例子来看,有些记录有一些相似性。但散列结果却没有。

谢谢!!

我认为您不需要担心UUID的重叠。

从正确的角度来看,人们被陨石撞击的年风险估计为170亿分之一,[38]这意味着概率约为0.00000000006(6×10−11),相当于一年内创建几十万亿个UUID并重复一次的几率。换句话说,只有在未来100年内每秒生成10亿个UUID后,只创建一个重复的概率才会达到50%左右。或者,换言之,如果地球上每个人都拥有6亿个UUID,那么一个重复的概率大约为50%。

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

继续使用String::uuid()和rest easy:)

UUID是唯一的

在cakphp-中插入记录时,我需要创建真正唯一的令牌

UUID就是这样的。它通常用于分布式系统中,以防止冲突(多个源将可能不同步的数据插入数据源)。

UUID不是安全措施

我需要它是独一无二的,同时非常非常安全

不确定对uuid进行哈希处理应该以何种方式增强安全性——它不会。依靠默默无闻的安全性或多或少会失败。

如果您需要某种形式的随机令牌,请使用哈希函数(对uuid进行哈希只是对随机种子进行哈希),如果您需要有保证的唯一标识符,请使用uuid。它们不是同一回事,UUID是一种非常糟糕的生成随机、非序列"UUID"的机制;不可猜测的";(或任何目的)字符串。

生成一个适用于加密目的的随机字符串在这里得到了很好的回答:

PHP 中的安全随机数生成

代码示例用随机二进制数据填充字符串$pr_bits,因此这些字符是不可打印的。要在URL中使用它,可以通过几种方式将二进制数据转换为可打印字符。它们都没有增强安全性,但使它们为URL做好了准备。

  1. 将字节转换为十六进制:bin2hex($pr_bits)
  2. 将字节转换为base64:base64_encode($pr_bits)
  3. 散列字节(因为输出方便地使用十六进制,而不是为了增加安全性):string hash ('md5' , $pr_bits)

我包括最后一个,因为你会看到人们出于其他原因使用散列函数,比如保证md5的输出是16字节/128位。在PHP中,人们使用它将值转换为HEX。

我提出了以下解决方案

使用字符串作为连接当前时间(以微秒为单位)和随机字符串的哈希的结果

$timeStr = str_replace("0.", "", microtime());
$timeStr = str_replace(" ", "", $timeStr);
echo Security::hash('random string').'_'.$timeStr;
// 5ffd3b852ccdd448809abb172e19bbb9c01a43a4_796473001379403705

因此,字符串的第一部分(哈希)将有助于令牌的不可访问性,第二部分将保证其唯一性。

希望这能帮助到别人。