2

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

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

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

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

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 确实是唯一的,但是从上面的例子来看,有些记录有一些相似之处。但散列结果没有。

谢谢 !!

4

4 回答 4

3

我认为您无需担心 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() 并放轻松:)

于 2014-04-17T18:51:00.600 回答
1

UUID 是唯一的

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

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

UUID 不是安全措施

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

不确定应该以何种方式散列 uuid 来增强安全性 - 它不会。依靠默默无闻的安全性或多或少肯定会失败。

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

于 2013-07-27T15:03:18.523 回答
1

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

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。

于 2013-07-27T15:36:51.550 回答
1

我想出了以下解决方案

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

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

// 5ffd3b852ccdd448809abb172e19bbb9c01a43a4_796473001379403705

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

希望,这会帮助某人。

于 2013-09-17T07:42:41.647 回答