我正在尝试计算哈希值,然后比较它们来模拟c#中的时间攻击 这是我为此目的使用的代码:
private void btnHash_Click(object sender, EventArgs e)
{
MD5 md5 = new MD5CryptoServiceProvider();
var firstHashByte = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(txtBoxText.Text));
txtBoxHash.Text = Convert.ToBase64String(firstHashByte);
var secondHashByte = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(txtBoxSecondText.Text));
txtBoxHashtwo.Text = Convert.ToBase64String(secondHashByte);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
NormalEquality(firstHashByte, secondHashByte);
//SlowEquals(firstHashByte, secondHashByte);
stopwatch.Stop();
lstBoxTimeSpan.Items.Add(stopwatch.ElapsedTicks.ToString());
}
private static void NormalEquality(byte[] hashByte, byte[] hashByte2)
{
bool bEqual = false;
if (hashByte.Length == hashByte2.Length)
{
int i = 0;
while ((i < hashByte2.Length) && (hashByte2[i] == hashByte[i]))
{
i += 1;
}
if (i == hashByte2.Length)
{
bEqual = true;
}
}
}
每次我尝试运行它时,即使是相同的哈希,我也会得到不同的时间! 为什么会这样? 我还注意到使用以下方法,据说为相同和不同的哈希值生成一个常量时间,并且它就像前一个方法一样,为任何事物生成不同的时间! (相同的哈希或不同的哈希!)
private static bool SlowEquals(byte[] a, byte[] b)
{
uint diff = (uint)a.Length ^ (uint)b.Length;
for (int i = 0; i < a.Length && i < b.Length; i++)
diff |= (uint)(a[i] ^ b[i]);
return diff == 0;
}
为什么会这样?任何的想法?
(顺便提一下:as C#string == compare在内部进行这种数组比较还是只是另一个故事? 因为每当我试图在Base64版本的哈希上使用==字符串时,我得到了0次,无论是相同的还是不同的哈希 我做了:
stopwatch.Start();
if ( firstHashString == secondHashString);
stopwatch.Stop();
)
答案 0 :(得分:1)
你会得到不同的时间因为秒表分辨率太低而无法测量如此少的代码。虽然秒表的分辨率非常高,但CPU仍然有时间在秒表的每个刻度之间运行数千条指令。
在执行该方法期间,秒表只会进行几次滴答,因此产生的时间会有很大差异。
如果您运行该方法一千次或一百万次,您就可以通过足够小的时间变化进行测量。
答案 1 :(得分:1)
有许多因素影响方法调用的时间,计算机是一个庞大的系统,最微小的变化可能成为众所周知的蝴蝶。坦率地说,微小的时间差异无需担心,重要的是它是否总能产生正确的结果。
尝试一件事可能是多次重复方法调用,例如。一百万次或一千万次,并计时所有的呼叫,例如。
stopwatch.Start();
for (int i=0; i<1000000; i++) {
// call test here
}
stopwatch.Stop();
如果你重复上述几次,时间应该非常接近。