生成密码安全令牌
为了生成一个32字符的令牌来访问我们的API,我们目前使用:
$token = md5(uniqid(mt_rand(), true));
我已经读过这种方法不是基于系统时钟的密码保护,而且openssl_random_pseudo_bytes
会是一个更好的解决scheme,因为它很难预测。
如果是这种情况,等效代码是什么样的?
我想这样的事情,但我不知道这是对的…
$token = md5(openssl_random_pseudo_bytes(32));
还有什么长度是有道理的,我应该传递给函数?
这是正确的解决scheme:
$token = bin2hex(openssl_random_pseudo_bytes(16)); # or in php7 $token = bin2hex(random_bytes(16));
如果你想使用openssl_random_pseudo_bytes,最好使用CrytoLib的实现,这将允许你生成所有的字母数字字符,坚持bin2hex围绕openssl_random_pseudo_bytes只会导致你得到AF(大写)和数字。
replacepath / to /放置cryptolib.php文件(你可以在GitHub上find它: https : //github.com/IcyApril/CryptoLib )
<?php require_once('path/to/cryptolib.php'); $token = CryptoLib::randomString(16); ?>
完整的CryptoLib文档可从以下url获得: https ://cryptolib.ju.je/。 它涵盖了许多其他随机方法,级联encryption和散列生成和validation; 但如果你需要的话,它就在那里。
如果你有一个密码安全的随机数发生器,你不需要散列它的输出。 其实你不想。 只是使用
$token = openssl_random_pseudo_bytes($BYTES,true)
其中$ BYTES是你想要的很多字节的数据。 MD5有一个128位的散列,所以16个字节就可以了。
作为一个便笺,您在原始代码中调用的函数没有一个是encryption安全的,大多数都是有害的,即使与安全的其他函数结合使用,也只会使一个函数不安全。 MD5有安全问题(虽然对于这个应用程序,它们可能不相关)。 Uniqid不仅不会默认生成密码随机字节(因为它使用系统时钟),所添加的熵通过使用线性一致的生成器进行组合,这不是密码安全的。 事实上,这可能意味着可以猜出所有的API密钥,只要他们不知道服务器时钟的价值,就可以访问其中的一些密钥。 最后,mt_rand(),你用作额外的熵,也不是一个安全的随机数发生器。
在PHP中没有简单的函数将string直接转换为string,它必须由自己实现! 就像这样: SafeToken 。