由于公司项目打算php升级到5.6版本,抽时间看了一下php5.6版本的更新,具体可参见从PHP 5.5.x 移植到 PHP 5.6.x

在阅读时,我发现该版本新增了一个函数hash_equals,而这个函数的解释是——可防止时序攻击的字符串比较。我的第一反应就是字符串比较就是===,或者strcmp不就可以了,怎么突然加了个函数,而且时序攻击又是什么,带着这些疑问只好去google了。

目前网上并没有任何详细的php hash_equals函数的具体解释,所以整理一篇文章分享给大家吧!

1. 边信道攻击

英文名side channel attack,简称SCA,又称侧信道攻击。针对加密电子设备在运行过程中的时间消耗、功率消耗或电磁辐射之类的侧信道信息泄露而对加密设备进行攻击的方法被称为边信道攻击。

这类攻击手段最大的特点是,并没有依赖数学算法进行破解攻击,但是效率上却可以比数学方法更高效。

针对这类攻击,通常是牺牲效率为代价进行防护,让运行程序的消耗量保持在固定常量。

2. 时序攻击

英文名Timing Attack,是边信道攻击中的一种,攻击者试图通过分析加密算法的执行时间来推导出密码。

举个例子,某个字符串比较函数,比较过程是是从第一位开始比较,发现不同就立即返回,那么通过计算返回的速度就知道了大概是哪一位开始不同的。

数据库存储密码为abc123,而我们传递的密码如果是000000,那么比较第一位不同就会返回。但是如果我们传递的密码是abc456,则比较到第四位才会发现不同。因此,通过不同的传值,目标机器的程序执行时间可能就会不同,进而通过运行时间逐步分析出真实数据。

3. 编程语言策略

我们以Microsoft CRT's implementation of memcmp函数为例子。

EXTERN_C int __cdecl memcmp(const void *Ptr1, const void *Ptr2, size_t Count)
{
    INT v = 0;
    BYTE *p1 = (BYTE *)Ptr1;
    BYTE *p2 = (BYTE *)Ptr2;
 
    while(Count-- > 0 && v == 0) {
        v = *(p1++) - *(p2++);
    }
 
    return v;
}

这个函数就存在这样的问题,更好的解决办法就是,不急着返回结果。

int util_cmp_const(const void * a, const void *b, const size_t size)
{
    const unsigned char *_a = (const unsigned char *) a;
    const unsigned char *_b = (const unsigned char *) b;
    unsigned char result = 0;
    size_t i;
 
    for (i = 0; i < size; i++) {
      result |= _a[i] ^ _b[i];
    }
 
    return result; /* returns 0 if equal, nonzero otherwise */
}

4. 关于php

可防止时序攻击的字符串比较——hash_equals
bool hash_equals ( string $known_string , string $user_string )

使用时注意参数存在先后顺序:
known_string
已知长度的、要参与比较的 string
user_string
用户提供的字符串

5. 难以利用的攻击

2005年4月,D.J. Bernstein公布了一种缓存时序攻击法,他以此破解了一个装载OpenSSL AES加密系统的客户服务器。为了设计使该服务器公布所有的时序信息,攻击算法使用了2亿多条筛选过的明码。有人认为,对于需要多个跳跃的国际互联网而言,这样的攻击方法并不实用。