我正在使用 Zend Framework 制作一个分类广告网站(出于投资组合的目的,是的,我知道世界上没有空间容纳“另一个 Craigslist 克隆”)。我正在尝试实现无需帐户即可发布/编辑/删除的功能。
为此,我觉得我需要在提交后生成一个随机数并将其存储在数据库中。然后通过电子邮件将链接发送给发出 GET 删除请求的用户,如下所示:
http://www.somesite.com/post/delete/?id=123&nonce=2JDXS93JFKS8204HJTHSLDH230945HSLDF
只有用户拥有这个唯一的 key 或随机数,提交后我会检查帖子 ID 下的数据库并确保随机数在删除之前匹配。
我的问题是随机数实际上有多安全。如果我使用 Zend Framework 的 Zend_Form_Element_Hash
,它会创建如下哈希:
protected function _generateHash()
{
$this->_hash = md5(
mt_rand(1,1000000)
. $this->getSalt()
. $this->getName()
. mt_rand(1,1000000)
);
$this->setValue($this->_hash);
}
在阅读 mt_rand() 时,one commenter said “此函数的熵有限。因此,如果您想创建随机字符串,无论字符串的长度如何,它都只会产生大约 20 亿个不同的字符串。如果您使用此类字符串,这可能会导致严重的安全问题用于 session 标识符、密码等。”
由于应用程序中随机数/ token 的生命周期(可能是用户选择删除帖子之前的几天或几周),我认为将为潜在的黑客攻击提供足够的时间。
我意识到 mt_rand()
是对 rand()
的巨大升级,如 this visual 中所示。左侧使用 rand
映射像素,右侧使用 mt_rand
映射像素。但这就足够了吗?是什么让“20 亿个不同的字符串”成为安全问题?
最终,如何增加随机数/ token /哈希的熵?
最佳答案
对于这样的安全性,输出的长度并不重要。它会计算您创建它时使用了多少随机性。
对于mt_rand()
,随机性的来源是它的种子和状态(自它被播种以来您使用它的次数)。更多的 mt_rand()
调用只会让您对相同的随机源进行更多的重新排序(没有新的熵)。
mt_rand()
的种子只有 32 位(任何小于 128 位的值都会让密码学家产生怀疑;)
具有 32 位熵的 key 的强度是 40 亿除以(大致)您将生成的 key 数量(例如,在使用 100K 次之后,将有大约 1:43000 的机会猜测任何有效 key ,这接近实用暴力破解)。
你在其中添加了盐,这使得它变得更强,因为除了猜测种子攻击者还必须知道盐之外,所以如果盐很长,那么总的来说, key 可能会相当强,尽管“低”熵。
为了增加熵,你需要添加更多来自与 mt_rand 不同来源的随机内容(即使是轻微随机也可以,只是提供更少的位):microtime()
、使用的内存量、进程 ID ...或者只是使用 /dev/random
,它收集它可以获得的所有熵。
(编辑:uniqid() 具有弱熵,因此它在这里没有帮助)
关于php - CSRF token 和随机数中的熵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9796216/