在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做好了准备。
- 将字节转换为十六进制:
bin2hex($pr_bits)
- 将字节转换为base64:
base64_encode($pr_bits)
- 散列字节(因为输出方便地使用十六进制,而不是为了增加安全性):
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
因此,字符串的第一部分(哈希)将有助于令牌的不可访问性,第二部分将保证其唯一性。
希望这能帮助到别人。