Php 安全字符串比较函数
我刚刚在Zend框架的HTTP Auth库中遇到了这段代码。它似乎在使用一个特殊的字符串比较函数来提高安全性。然而,我不太理解这些评论。有人能解释一下为什么这个函数比执行Php 安全字符串比较函数,php,string,security,zend-framework,compare,Php,String,Security,Zend Framework,Compare,我刚刚在Zend框架的HTTP Auth库中遇到了这段代码。它似乎在使用一个特殊的字符串比较函数来提高安全性。然而,我不太理解这些评论。有人能解释一下为什么这个函数比执行$a==$b更安全吗 /** * Securely compare two strings for equality while avoided C level memcmp() * optimisations capable of leaking timing information useful to an attack
$a==$b
更安全吗
/**
* Securely compare two strings for equality while avoided C level memcmp()
* optimisations capable of leaking timing information useful to an attacker
* attempting to iteratively guess the unknown string (e.g. password) being
* compared against.
*
* @param string $a
* @param string $b
* @return bool
*/
protected function _secureStringCompare($a, $b)
{
if (strlen($a) !== strlen($b)) {
return false;
}
$result = 0;
for ($i = 0; $i < strlen($a); $i++) {
$result |= ord($a[$i]) ^ ord($b[$i]);
}
return $result == 0;
}
/**
*安全地比较两个字符串是否相等,同时避免使用C级别的memcmp()
*能够泄漏对攻击者有用的定时信息的优化
*尝试迭代地猜测正在使用的未知字符串(例如密码)
*与…相比。
*
*@param string$a
*@param字符串$b
*@returnbool
*/
受保护的函数\u secureStringCompare($a,$b)
{
if(strlen($a)!==strlen($b)){
返回false;
}
$result=0;
对于($i=0;$i
看起来他们在试图阻止
在密码学中,定时攻击是一种侧通道攻击,在这种攻击中,攻击者试图通过分析执行密码算法所花费的时间来破坏密码系统。计算机中的每一个逻辑操作都需要时间来执行,时间根据输入的不同而不同;通过精确测量每个操作的时间,攻击者可以向后操作输入
基本上,如果比较正确的密码和错误的密码需要不同的时间,那么您可以使用计时来计算您正确猜测的密码字符数
考虑一个有严重缺陷的字符串比较(这基本上是正常的字符串相等函数,添加了一个明显的wait
):
它允许您使用定时攻击来计算密码的正确长度,这样您就不用费心猜测任何更短或更长的密码。一般来说,第一个(这将创建相等长度的字符串),所以我猜他们不认为这是个问题。“不要去那里,因为那里很危险,但无论如何都要去那里,因为那是唯一的道路”@rook-为什么它是正确的?从代码中的注释来看,ZEDN正试图做到这一点。@ IWANTSILLIFLIFE——考虑一个情况,即您不在散列密码,正确的密码是5个字符长。如果您提交的密码长度为1个字符,它将立即返回。长度为2个字符时,它将立即返回,以此类推,最多返回5个字符,此时它将突然花费稍长的时间,然后在长度为6时,它将立即再次返回。即使
strlen
没有以固定时间返回(比如更长的字符串需要更长的时间),您仍然可以进行回归,并找出比较需要更长的时间。@iWantSimpleLife:密码应始终以预先散列的方式存储在数据库中。是的。但是我们这里讨论的是功能的实现,而不是一般的安全性这就是PHP5.6中的hash_equals
所做的+
function compare(a, b) {
if(len(a) !== len(b)) {
return false;
}
for(i = 0; i < len(a); ++i) {
if(a[i] !== b[i]) {
return false;
}
wait(10); // wait 10 ms
}
return true;
}
if(strlen($a) !== strlen($b)) {
return false;
}