我有两个问题不明白。请帮我看看。谢谢
MessageDigest.isEqual函数在Java中有什么用途?
解释为什么在Java SE 6 Update 17之前的某些版本中,它容易受到定时攻击。
查看Java SE 6 Update 10的实现,我们看到:
public static boolean isEqual(byte digesta[], byte digestb[]) {
if (digesta.length != digestb.length)
return false;
for (int i = 0; i < digesta.length; i++) {
if (digesta[i] != digestb[i]) {
return false;
}
}
return true;
}
而在修复后,我们看到:
public static boolean isEqual(byte[] digesta, byte[] digestb) {
if (digesta.length != digestb.length) {
return false;
}
int result = 0;
// time-constant comparison
for (int i = 0; i < digesta.length; i++) {
result |= digesta[i] ^ digestb[i];
}
return result == 0;
}
旧的实现似乎更有效,因为当找到第一个不相等的字节时,它会返回false
,但我假设它被替换了,因为它可能允许调用方根据方法的运行时间测试两个输入字节数组的相似程度。
新实现总是具有相同的运行时间(对于相同长度的数组),因为它在整个数组上迭代(即使数组的第一个字节不同)。
我搜索了调用此方法的位置。一个例子是com.sun.org.apache.xml.internal.security.algorithms.implementations.IntegrityHmac
类中的engineVerify(byte[] signature)
,它通过将传递给它的签名字节数组与某个内部字节数组进行比较来测试它是否有效。在修复之前,通过测量该方法的运行时间,您可以尝试生成一个通过比较的字节数组(该方法运行的时间越长,意味着两个数组的前缀越大)。
请参阅下面的网页链接:http://codahale.com/a-lesson-in-timing-attacks/
我可以选择我想要验证的消息——比如说一个具有特定用户ID的会话cookie——然后计算256个可能的值:
0000000000000000000000000000000000000000
0100000000000000000000000000000000000000
0200000000000000000000000000000000000000
... snip 250 ...
FD00000000000000000000000000000000000000
FE00000000000000000000000000000000000000
FF00000000000000000000000000000000000000
我遍历了这些值中的每一个,直到找到一个——A1000000000000000000000000000000——它比其他值长几分之一毫秒。我现在知道该消息的HMAC的第一个字节应该是A1。对剩下的19个字节重复这个过程,突然间我以您的身份登录了。