MessageDigest.isEqual函数在Java中使用

use*_*809 10 java timing-attack

我有两个问题,我不明白.请帮我看看.谢谢.

  1. Java中的MessageDigest.isEqual函数有什么用?

  2. 解释为什么在Java SE 6 Update 17之前的某些版本中,它容易受到定时攻击.

Era*_*ran 9

查看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;
}
Run Code Online (Sandbox Code Playgroud)

在修复之后我们看到:

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;
}
Run Code Online (Sandbox Code Playgroud)

旧的实现似乎更有效,因为它false在找到第一个非相等字节时返回,但我假设它被替换,因为它可能允许调用者测试两个输入字节数组彼此有多相似关于方法的运行时间.

新实现总是具有相同的运行时间(对于相同长度的数组),因为它遍历整个数组(即使数组的第一个字节不同).

我搜索了这个方法被调用的地方.一个例子是engineVerify(byte[] signature)com.sun.org.apache.xml.internal.security.algorithms.implementations.IntegrityHmac类中,它通过将它与一些内部字节数组进行比较来测试传递给它的签名字节数组是否有效.在修复之前,通过测量该方法的运行时间,您可以尝试生成将通过比较的字节数组(方法运行所需的时间越长意味着两个数组的更大前缀相等).