很多代码都会做这样的事情来生成某种秘密:
sha1(random())
为什么不简单地使用随机数?我意识到在过去,一些操作系统随机生成器并不是那么好,但我不确定这是否仍然是正确的,即使是这样,sha1'ing 如何让它变得更好?
很多代码都会做这样的事情来生成某种秘密:
sha1(random())
为什么不简单地使用随机数?我意识到在过去,一些操作系统随机生成器并不是那么好,但我不确定这是否仍然是正确的,即使是这样,sha1'ing 如何让它变得更好?
我怀疑哈希函数经常被误用作编码函数。需要一个一定长度的字母数字代码,而散列提供了这样一个字符串。这很容易,而且看起来不可预测。
很容易忘记,随机部分不是 md5 的 32 个十六进制字符,而是函数提供md5(random())
的可能结果。random()
如果知道随机函数是如何工作的,就可以预先计算出一系列可能的值。
如果您真的使用操作系统的随机源,并且请求尽可能多的字节,那么代码会更加随机(更好的熵)。然后,您可以使用类似的函数对这些字节进行编码base64_encode()
。对于令牌,base62 编码将是理想的,因为它非常紧凑并且不返回特殊字符,尽管实现起来有点困难。
回答您的问题:随机数会更好,但它必须是“真正”随机的。如果您将其用作仅带有“0”-“9”的字母数字,那么您的令牌会很长,可以使用编码功能将其缩短。
如果您正在生成一个秘密,您应该使用加密安全的随机数或伪随机数生成器。散列一个非密码安全的随机数是一种隐蔽的安全形式,而不是真正的安全措施。
它增加了一个步骤来找出秘密,这可能就是它完成的原因,但它并没有使秘密安全。
您不想使用随机数而不是散列,因为这样攻击者就更容易猜测您的来源并创建他自己的“秘密”(特别是如果您使用系统时钟,永远不要这样做。请参阅正在使用microtime() 生成密码重置令牌不好的做法)。从随机化的角度来看,真正的随机数并不比随机数的散列更好,但它掩盖了模式,以至于人类无法识别任何变化模式(例如种子值)。此外,它确实增强了安全性,因为当攻击者必须在提交之前对每次尝试进行哈希处理时,暴力攻击需要更长的时间。对于像 SHA-256 这样的强散列尤其如此。当每次提交都需要处理器密集型操作时,蛮力攻击所需的计算时间会显着增加。这就是 Linux 从将密码哈希存储为 MD5 到 SHA 的原因。
此外,SHA 和其他散列具有一些有利于安全性的数学优势。首先,无论输入长度如何,它们总是输出相同的长度。其次,输入的微小变化会导致输出的巨大变化,而对于输出的微小变化,获得该输出所需的相应输入将比之前的输入差异大得多。这使得攻击者很难通过选择性地提供输入来生成他们想要的哈希,并且几乎不可能两个相似的输入产生相同甚至非常接近的输出。
这是一个很深的话题,可以写一整本教科书,但这只是一些高层次的原因。