【发布时间】:2014-10-11 23:37:00
【问题描述】:
(注意:“恒定时间”是指当其中一个输入固定时,机器周期数是恒定的,而不是 O(1)。这是该术语在密码学上下文中的标准含义。)
比较一个固定值和一个相同大小的未知值以保证不会通过时序泄露有关固定值的信息的最常见方法是使用 XOR 循环:
bool compare(const char* fixed, const char* unknown, size_t n)
{
char c = 0;
for (size_t i=0; i<n; ++i)
c |= fixed[i] ^ unknown[i];
return (c == 0);
}
GCC 4.6.3 和 CLANG 3.0 不会在 AMD64 上短路这个循环,即使在 -O3 时也是如此(我检查了生成的机器代码)。但是,我不知道 C 标准中有什么会阻止一些聪明的编译器识别如果c 永远非零,那么函数只能返回false。
如果您愿意接受较大的性能损失和概率比较而不是确定性比较,那么实现恒定时间比较的更偏执的方法是计算两个输入的加密哈希值并比较这些哈希值;如何比较散列并不重要,因为除非攻击者可以计算散列的原像,否则它无法对未知值进行连续逼近。很难想象一个编译器足够聪明来优化它,但我不能保证它不会发生。更偏执的方法是使用带有特定于实例的密钥而不是简单的哈希的 HMAC,尽管我仍然可以想象一个神奇的智能优化器,它认识到无论使用什么密钥,它正在编译的算法只是一种缓慢的方式进行字符串比较并进行相应的优化。通过添加额外的复杂层、对共享库的调用等,我可以使我的比较难以优化,但我仍然不能保证没有符合标准的编译器可以缩短我的比较并让我容易受到定时攻击。
有没有什么方法可以实现高效、确定性、恒定时间的比较,保证始终符合 C 标准?如果没有,是否有任何流行的 C(或 C++)编译器或库提供这种方法?请引用您的来源。
【问题讨论】:
-
“恒定时间”是指 O(1),还是“总是花费相同的时间来运行,无论输入如何,因此适合加密使用? "
-
OP 很清楚的意思是后者。
-
@templatetypedef:我的意思是当输入之一固定时,比较总是在相同数量的机器周期内运行。换句话说,没有时序侧通道可用于计算固定输入的值。
标签: c++ c optimization comparison standards