在不依赖于典型 PHP 安装中很少包含的库的情况下,在 PHP 中生成加密安全的 32 字节盐的最佳方法是什么?
经过一番谷歌搜索后,我发现这mt_rand
被认为不够安全,但我还没有找到替代建议。一篇文章建议阅读/dev/random
但不仅这在 Windows 上不起作用;它也很慢。
我希望在安全性和速度之间取得合理的平衡(即,生成 512 字节不应该像/dev/random
通常那样需要 20 秒)
在不依赖于典型 PHP 安装中很少包含的库的情况下,在 PHP 中生成加密安全的 32 字节盐的最佳方法是什么?
经过一番谷歌搜索后,我发现这mt_rand
被认为不够安全,但我还没有找到替代建议。一篇文章建议阅读/dev/random
但不仅这在 Windows 上不起作用;它也很慢。
我希望在安全性和速度之间取得合理的平衡(即,生成 512 字节不应该像/dev/random
通常那样需要 20 秒)
这在 PHP 7 中更容易:只需用于$salt = random_bytes($numberOfDesiredBytes);
生成盐。
无论如何,你需要盐做什么?如果是密码,只需使用password_hash()
and password_verify()
。
注意:
mcrypt
在 PHP 7.1 中已被弃用。跳到最新答案。
您可能想查看mcrypt_create_iv()
.
注意:
mcrypt
在 PHP 7.1 中已被弃用。跳到最新答案。
您可以使用该函数mycrypt_create_iv()
,因为 PHP 版本 5.3 它还使用 Windows 服务器上的随机源(不仅在 Unix 上)。在使用它之前,您应该检查该常量MCRYPT_DEV_URANDOM
是否已定义。
mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
与随机不同,如果没有足够的熵可用,urandom 不会阻塞服务器。由于密码盐应该是唯一的(不一定是随机的),所以 urandom 对我来说似乎是一个不错的选择。
uniqueid
不太适合生成随机字符串,因为它也是microtime
基于的。CPU 周期通常比 microtime-tick 短得多,这可能导致循环内给定变量可能保持不变。将第二个参数“entropy”设置为true,
uniqid('', true)
将提供增加的随机性。
要获得与大多数字符集很好兼容的随机字符串,可以将 base64 编码应用于mcrypt初始化向量函数mcrypt_create_iv
:
$length = 16;
base64_encode(mcrypt_create_iv(ceil(0.75*$length), MCRYPT_DEV_URANDOM))
//> hlZuRJypdHFQPtI2oSFrgA==
strlen(base64_encode(mcrypt_create_iv(ceil(0.75*$length), MCRYPT_DEV_URANDOM)))
//> 16
将字符字母减少到 2^6Bit 会增加大小,这在上面已经说明。
阅读/dev/urandom
或使用openssl_random_pseudo_bytes()
.
看起来这个问题有一个可以接受的答案,但我只想在经过一些研究并阅读这个帖子后另外声明,如果你不把所有的鸡蛋都放在一个篮子里,你可能会增加一些安全性。
我可能建议不要仅仅依靠 PHP 来创建你的盐和散列你的密码。如果您让数据库完成部分工作,您可以进一步混淆您的解决方案。
有人建议只使用 password_hash() 和 password_verify()。虽然这些都是很好的方法,但我强烈建议坚持在这些方法之外加入盐的想法。
为了回答这个问题,盐可以是真正随机的任何东西,并且对用户来说是唯一的。只要您遵守这两条规则,您就可以在技术上按照您的意愿生成它。
几个很好的资源:
https://www.codeproject.com/Articles/704865/Salted-Password-Hashing-Doing-it-Right https://auth0.com/blog/adding-salt-to-hashing-a-better-way-to -存储密码/
uniqid()应该可以用于此目的。
我觉得microtime()
够了。
奇怪的是,但我仍然对这个答案投了反对票。
虽然我得到的唯一解释是微时间是可以预测的。
这对我来说听起来很奇怪,因为盐总是被认为是众所周知的——所以,预测根本没有用。