13

我想使用 php 生成加密安全的唯一 uuid。

uniqid() 提供唯一但不安全的 ID,而 openssl_random_pseudo_bytes() 提供安全但不唯一的 ID。两者的结合(以下代码)是正确的方法还是有更好的解决方案?

uniqid(bin2hex(openssl_random_pseudo_bytes(10)), true);
4

3 回答 3

11

我想使用 php 生成加密安全的唯一 uuid。

好的,这很容易做到。

uniqid() 提供唯一但不安全的 ID,而 openssl_random_pseudo_bytes() 提供安全但不唯一的 ID。

是什么让您认为加密安全的伪随机数不是唯一的?

/**
 * Return a UUID (version 4) using random bytes
 * Note that version 4 follows the format:
 *     xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
 * where y is one of: [8, 9, A, B]
 * 
 * We use (random_bytes(1) & 0x0F) | 0x40 to force
 * the first character of hex value to always be 4
 * in the appropriate position.
 * 
 * For 4: http://3v4l.org/q2JN9
 * For Y: http://3v4l.org/EsGSU
 * For the whole shebang: https://3v4l.org/LNgJb
 * 
 * @ref https://stackoverflow.com/a/31460273/2224584
 * @ref https://paragonie.com/b/JvICXzh_jhLyt4y3
 * 
 * @return string
 */
function uuidv4()
{
    return implode('-', [
        bin2hex(random_bytes(4)),
        bin2hex(random_bytes(2)),
        bin2hex(chr((ord(random_bytes(1)) & 0x0F) | 0x40)) . bin2hex(random_bytes(1)),
        bin2hex(chr((ord(random_bytes(1)) & 0x3F) | 0x80)) . bin2hex(random_bytes(1)),
        bin2hex(random_bytes(6))
    ]);
}

上面的例子符合UUIDv4规范,使用了PHP7的random_bytes()功能。

对于 PHP 5 项目,您可以使用random_compatrandom_bytes()从 PHP 7进行polyfill。

于 2015-07-16T16:58:12.757 回答
0

尽管最佳答案实际上是正确的,但在理论上并不正确。

你的问题也没有完美的答案。

安全性依赖于公正、不可预测、真正的随机性。但是真正随机的东西总是可以重复的,或者它不会是随机的。一个百万面的骰子可以连续一百万次落在同一个数字上,这种情况发生的可能性非常小。

UUIDv4 的优势在于两次获得相同 ID(碰撞)的概率非常小,“两次从星系中挑选同一个原子”的概率很小。

任何增加唯一性的尝试实际上都会降低安全性。您可以添加微秒时间戳或自动递增值和毫米精度空间坐标以保证唯一性。但随后您添加了有关创建 ID 的位置、方式和顺序的信息......

同样,出于所有实际目的,使用 UUIDv4 作为安全且唯一的标识符是安全的。

还要意识到 , md5,sha1uniqid本身并不完美,以随机方式组合它们并不一定会减少碰撞或增加安全性。散列函数充其量与您正在散列的事物一样唯一,并且通常它们会降低唯一性。

答案总是在于随机性加上长度。

于 2016-10-27T11:50:01.360 回答
-1

为什么不对 openssl_random_pseudo_bytes 的输出进行哈希处理?您还可以连接时间戳并在之后对其进行哈希处理

md5(bin2hex(openssl_random_pseudo_bytes(10)).strval(time()));

以 md5 为例。您可以使用任何哈希算法。

于 2015-07-16T10:24:32.140 回答