I found the following code snippet from the Bouncy Castle C# library, which seems to claim that it's constant time, even when the arrays have different lengths.
/// <summary>
/// A constant time equals comparison - does not terminate early if
/// test will fail.
/// </summary>
/// <param name="a">first array</param>
/// <param name="b">second array</param>
/// <returns>true if arrays equal, false otherwise.</returns>
public static bool ConstantTimeAreEqual(byte[] a, byte[] b)
{
if (null == a || null == b)
return false;
if (a == b)
return true;
int len = System.Math.Min(a.Length, b.Length);
int nonEqual = a.Length ^ b.Length;
for (int i = 0; i < len; ++i)
{
nonEqual |= (a[i] ^ b[i]);
}
for (int i = len; i < b.Length; ++i)
{
nonEqual |= (b[i] ^ ~b[i]);
}
return 0 == nonEqual;
}
However, I've heard that it's not possible to compare arrays of different sizes in constant time. For instance, the Go crypto ConstantTimeCompare() function checks the length of the arrays before the comparison. Some people have complained that this leaks the length of the secret.
func ConstantTimeCompare(x, y []byte) int {
if len(x) != len(y) { // <--- here
return 0
}
var v byte
for i := 0; i < len(x); i++ {
v |= x[i] ^ y[i]
}
return ConstantTimeByteEq(v, 0)
}
Which approach should be taken when comparing arrays of different lengths? Or should you just hash the data and then perform the comparison (since the lengths will be the same)?