【发布时间】:2013-09-20 18:28:07
【问题描述】:
为了生成一个 32 字符的令牌来访问我们目前使用的 API:
$token = md5(uniqid(mt_rand(), true));
我了解到这种方法在密码学上并不安全,因为它基于系统时钟,并且openssl_random_pseudo_bytes 将是一个更好的解决方案,因为它更难预测。
如果是这种情况,等效代码会是什么样子?
我推测是这样的,但我不知道这是否正确......
$token = md5(openssl_random_pseudo_bytes(32));
还有我应该传递给函数的长度是多少?
【问题讨论】:
-
为什么是 md5 呢?只需将字节流转换为十六进制:您将从 openssl_random_pseudo_bytes() 返回 32 个字节,使用 bin2hex() 将这些字节中的每一个渲染为十六进制值,如 PHP docs 示例中所示
-
我只想要 32 个字符?我该怎么做?
-
md5()生成一个 32 个字符的字符串,但其中只有 128 位的数据。openssl_random_pseudo_bytes()返回真正的二进制数据,因此具有 32*8 = 256 位的随机性。通过将 32 字节的随机字符串填充到 md5 中,您有效地大量削减了它的唯一性。 -
那么
$token = bin2hex(openssl_random_pseudo_bytes(16));足够了吗,还是我需要一个16次迭代的循环,将1作为长度并以十六进制附加到字符串? -
16字节转十六进制的最终解法是正确的。但是你不应该在这里真正依赖 OpenSSL #1 #2 #3。一旦您使用 PHP 7.0+,就真的没有理由再使用它了。尝试使用
Random::alphanumericString($length),而不是 OpenSSL 和十六进制编码,它可以将大约 20 亿倍的“熵”放入这 16 个字符中。
标签: php security openssl token