我正在使用md5(uniqid())
为我的表单上的令牌隐藏输入(例如登录,注册,设置等)为我的文件共享和托管服务以及用户会话生成一个唯一的哈希值,所以我可以在表格提交后比较这两个。
但是在我读到md5有很多安全漏洞后,我想知道md5(uniqid())
是否足够好。
是否有更好或更安全的方式为表单生成令牌?
输出示例
<input type="hidden" name="token" value="4c1dd84d3458964ee6d59c728dc70160">
答案 0 :(得分:2)
此令牌应该是一个不可预测的代码。使用确定性计算机获得这种不可预测的代码的最佳方法是生成一个非常随机的数字。
当你的uniqid使用MD5功能时,它不会为你的令牌添加任何随机性/不可预测性,你(错误地)将它用作编码器。使用bin2hex()
函数可以获得相同的目标,这是MD5在计算二进制哈希值后默认执行的操作。也就是说,MD5功能在这里并不安全,但也没有任何优势。
更重要的一点是,函数uniqid()
不可预测,它基于当前时间戳。这是代码中不安全的部分。要获得不可预测的数字,您可以使用从操作系统的随机源读取的函数mcrypt_create_iv()
。
我建议让PHP使用session_start()
函数为您创建会话令牌。如果您确实有理由不使用普通的PHP会话,请将mcrypt_create_iv()
与bin2hex()
或base64_encode()
等编码函数一起使用。
修改强>
根据您的评论,我看到此令牌不用于维护会话,而是用于缓解csrf。在这种情况下,session_start函数当然不会有用(会话ID不应该用作csrf标记),但是创建一个不可预测的标记仍然很重要。这是如何做到这一点的一个例子:
/**
* Generates a random string of a given length, using the random source of
* the operating system. The string contains only characters of this
* alphabet: +/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
* @param int $length Number of characters the string should have.
* @return string A random base64 encoded string.
*/
protected static function generateRandomBase64String($length)
{
if (!defined('MCRYPT_DEV_URANDOM')) throw new Exception('The MCRYPT_DEV_URANDOM source is required (PHP 5.3).');
// Generate random bytes, using the operating system's random source.
// Since PHP 5.3 this also uses the random source on a Windows server.
// Unlike /dev/random, the /dev/urandom does not block the server, if
// there is not enough entropy available.
$binaryLength = (int)($length * 3 / 4 + 1);
$randomBinaryString = mcrypt_create_iv($binaryLength, MCRYPT_DEV_URANDOM);
$randomBase64String = base64_encode($randomBinaryString);
return substr($randomBase64String, 0, $length);
}
答案 1 :(得分:1)
上半年有一个很好的答案 https://security.stackexchange.com/a/19710,下半部神从联机帮助页上得到了一个很好的答案,由rmcfrazier发布:http://www.php.net/manual/en/function.uniqid.php
引用组合学: “MD5上存在毁灭性的碰撞攻击。(...)相比之下,SHA1似乎更加安全。虽然有一些已知的SHA1攻击,但它们远不如对MD5的攻击严重。因此,SHA1在许多情况下,它是比MD5更好的选择。“ &lt; - MD5
“警告:此函数不会创建随机或不可预测的字符串。此功能不得用于安全目的。使用加密安全随机函数/生成器和加密安全散列函数来创建不可预测的安全ID。” &lt; - uniqid
答案 2 :(得分:0)
根据手册页,这不应该用于加密安全令牌 http://www.php.net/manual/en/function.uniqid.php
您应该使用openssl_random_pseudo_bytes作为令牌 http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php
答案 3 :(得分:0)
这实际上取决于您需要令牌的安全性。除非您需要在提交后验证密钥的完整性,否则使用PHP会话ID就足够了。
EG。 PHP会话ID:
php > session_start();
php > echo session_id();
ritig5ecgp6ebmnq8p5imbdhl3
但是,您始终可以使用hash()
功能生成更安全的ID,例如:
http://us2.php.net/manual/en/function.hash.php 不要使用RipeMD
echo hash('ripemd160', 'The quick brown fox jumped over the lazy dog.');
ec457d0a974c48d5685a7efa03d137dc8bbde7e3
除非令牌需要加密安全,否则会话密钥就足够了。