我正在使用Zend Framework制作一个分类广告网站(出于投资组合的目的,是的,我知道世界上还没有“另一个Craigslist克隆”的空间)。我正在尝试实现发布/编辑/删除的功能,而无需帐户。
要做到这一点,我觉得我需要在提交后生成Nonce并存储在数据库中。然后通过电子邮件发送给用户的链接,该链接发出删除的GET请求,如下所示:
http://www.somesite.com/post/delete/?id=123&nonce=2JDXS93JFKS8204HJTHSLDH230945HSLDF
只有用户拥有此唯一密钥或nonce,并且在提交后我会检查帖子ID下的数据库,并确保在删除之前匹配nonce。
我的问题是nonce实际上是多么安全。如果我使用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亿个不同的字符串,无论长度如何字符串。如果您使用此类字符串作为会话标识符,密码等,这可能是严重的安全问题。“
由于应用程序中nonce / token的生命周期,可能是用户选择删除帖子之前的几天或几周,我认为可能会有足够的时间来进行潜在的黑客攻击。
我意识到mt_rand()
是rand()
的巨大升级,如this visual映射像素左侧rand
和右侧mt_rand
所示。但这够了吗?是什么让“ 20亿个不同的字符串”成为安全问题?
最终,如何增加现时/令牌/哈希的熵?
答案 0 :(得分:1)
对于这种安全性,输出的时间长短不仅重要。它计算你用来创建它的随机性。
对于mt_rand()
,随机源是它的种子和状态(自播种以来你使用它的次数)。更多mt_rand()
次调用只会让您重新获得相同的随机源(没有新的熵)。
mt_rand()
的种子只有32位(任何小于128位的密码都会让密码学家怀疑;)
具有32位熵的密钥的强度是40亿除以(大致)您将生成的密钥数量(例如,在100K使用之后,将有~1:43000的机会猜测任何有效密钥,这接近实际暴力破解)。
你正在添加盐,这使得它更强大,因为除了猜测种子攻击者也必须知道盐,所以如果盐很长,那么整体关键可能相当强大尽管“低”熵。
为了增加熵,您需要添加更多随机内容(即使稍微随机也可以,只是提供更少的位)来自不同的源,而不是mt_rand:microtime()
,使用的内存量,进程ID ...或者只是使用/dev/random
,它可以收集它可以获得的所有熵。
(编辑:uniqid()有弱熵,所以在这里没有帮助)
答案 1 :(得分:1)
上面用于md5()散列函数的输入的Zend散列生成代码具有1,000,000 X 1,000,000种不同的可能性。无论输入是什么,md5()都有32 ^ 16(1208925819614629174706176)可能的结果。平均而言,黑客需要向您的服务器发送500,000,000,000个请求才能猜出正确的随机数。
每分钟100次请求,大约需要3472222天才能入侵。