为什么密码哈希验证应该是时间常数?

信息安全 密码 哈希
2021-08-26 02:20:53

在 asp.net 核心PasswordHasher类型中,VerifyHashedPassword 方法上有备注

 /// <remarks>Implementations of this method should be time consistent.</remarks>

然后为了比较散列,它使用故意不优化和编写的代码,不要在循环中提前退出。

// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static bool ByteArraysEqual(byte[] a, byte[] b)
{
    if (a == null && b == null)
    {
        return true;
    }
    if (a == null || b == null || a.Length != b.Length)
    {
        return false;
    }
    var areSame = true;
    for (var i = 0; i < a.Length; i++)
    {
       areSame &= (a[i] == b[i]);
    }
    return areSame;
}

起初我认为没有这个时间可以用来确定散列有多接近,如果需要更长的时间,那么更多的散列是相同的。

然而,这没有任何意义,因为此时哈希已经经历了 1000 次 SHA256 迭代。因此,密码的任何更改都会产生完全不同的哈希值,并且知道您的密码产生几乎正确的哈希值并不能帮助您找到正确的哈希值。

确保恒定时间哈希验证的目的是什么?

1个回答

假设两个哈希都不是秘密的并且哈希是安全的(SHA-256 是安全的),没有理由在恒定时间内检查哈希。事实上,比较哈希是在恒定时间例程内验证密码的众所周知的替代方法之一。我不能说开发人员会给出什么理由这样做,但技术上没有必要让它恒定时间。很可能,他们只是谨慎行事。密码库中的非恒定时间码使审计人员感到焦虑。

有关理论弱点的更多信息,请参阅 Cryptography 网站上的答案。它解释了如何通过大量查询来发现散列的前几个字节,这使得执行离线计算以丢弃显然不匹配的候选密码成为可能(它们的散列不匹配)匹配真实哈希的前几个发现的字节)并避免将它们发送到密码检查服务,以及为什么这不太可能是一个真正的问题。