C# C语言中的哈希摘要/数组比较
我正在编写一个需要验证HMAC-SHA256校验和的应用程序。我目前拥有的代码如下所示:C# C语言中的哈希摘要/数组比较,c#,security,timing,string-comparison,C#,Security,Timing,String Comparison,我正在编写一个需要验证HMAC-SHA256校验和的应用程序。我目前拥有的代码如下所示: static bool VerifyIntegrity(string secret, string checksum, string data) { // Verify HMAC-SHA256 Checksum byte[] key = System.Text.Encoding.UTF8.GetBytes(secret); byte[] val
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = System.Text.Encoding.UTF8.GetBytes(secret);
byte[] value = System.Text.Encoding.UTF8.GetBytes(data);
byte[] checksum_bytes = System.Text.Encoding.UTF8.GetBytes(checksum);
using (var hmac = new HMACSHA256(key))
{
byte[] expected_bytes = hmac.ComputeHash(value);
return checksum_bytes.SequenceEqual(expected_bytes);
}
}
public static bool CompareArraysExhaustively(byte[] first, byte[] second)
{
if (first.Length != second.Length)
{
return false;
}
bool ret = true;
for (int i = 0; i < first.Length; i++)
{
ret = ret & (first[i] == second[i]);
}
return ret;
}
checksum_bytes.Zip( expected_bytes, (a,b) => a == b ).Aggregate( true, (a,r) => a && r );
我知道这很容易受到影响
标准库中是否有消息摘要比较功能?我意识到我可以编写自己的时间硬化比较方法,但我必须相信这已经在其他地方实现了。它如何容易受到定时攻击?在有效或无效摘要的情况下,代码的工作时间相同。计算摘要/检查摘要看起来是检查这一点的最简单方法。它如何容易受到定时攻击?在有效或无效摘要的情况下,代码的工作时间相同。计算摘要/检查摘要看起来是检查这一点的最简单方法。编辑:原始答案如下-在我看来仍然值得一读,但关于计时攻击 您引用的页面提供了一些关于编译器优化的有趣观点。假设校验和的大小不是特别机密,您知道两个字节数组的长度相同,那么如果长度不同,您可以立即返回,您可以尝试以下方法:
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = System.Text.Encoding.UTF8.GetBytes(secret);
byte[] value = System.Text.Encoding.UTF8.GetBytes(data);
byte[] checksum_bytes = System.Text.Encoding.UTF8.GetBytes(checksum);
using (var hmac = new HMACSHA256(key))
{
byte[] expected_bytes = hmac.ComputeHash(value);
return checksum_bytes.SequenceEqual(expected_bytes);
}
}
public static bool CompareArraysExhaustively(byte[] first, byte[] second)
{
if (first.Length != second.Length)
{
return false;
}
bool ret = true;
for (int i = 0; i < first.Length; i++)
{
ret = ret & (first[i] == second[i]);
}
return ret;
}
checksum_bytes.Zip( expected_bytes, (a,b) => a == b ).Aggregate( true, (a,r) => a && r );
另一方面,您可以对实际哈希进行Base64编码,而不是在字节数组上使用SequenceEqual,并查看其是否匹配:
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = Encoding.UTF8.GetBytes(secret);
byte[] value = Encoding.UTF8.GetBytes(data);
using (var hmac = new HMACSHA256(key))
{
return checksum == Convert.ToBase64String(hmac.ComputeHash(value));
}
}
我不知道在这个框架内还有什么更好的。为数组或常规ICollection实现编写一个专门的SequenceEqual运算符并不难,因为它首先检查长度是否相等。。。但是考虑到散列的长度很短,我就不担心了。编辑:原始答案如下-在我看来仍然值得一读,但是关于定时攻击 您引用的页面提供了一些关于编译器优化的有趣观点。假设校验和的大小不是特别机密,您知道两个字节数组的长度相同,那么如果长度不同,您可以立即返回,您可以尝试以下方法:
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = System.Text.Encoding.UTF8.GetBytes(secret);
byte[] value = System.Text.Encoding.UTF8.GetBytes(data);
byte[] checksum_bytes = System.Text.Encoding.UTF8.GetBytes(checksum);
using (var hmac = new HMACSHA256(key))
{
byte[] expected_bytes = hmac.ComputeHash(value);
return checksum_bytes.SequenceEqual(expected_bytes);
}
}
public static bool CompareArraysExhaustively(byte[] first, byte[] second)
{
if (first.Length != second.Length)
{
return false;
}
bool ret = true;
for (int i = 0; i < first.Length; i++)
{
ret = ret & (first[i] == second[i]);
}
return ret;
}
checksum_bytes.Zip( expected_bytes, (a,b) => a == b ).Aggregate( true, (a,r) => a && r );
另一方面,您可以对实际哈希进行Base64编码,而不是在字节数组上使用SequenceEqual,并查看其是否匹配:
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = Encoding.UTF8.GetBytes(secret);
byte[] value = Encoding.UTF8.GetBytes(data);
using (var hmac = new HMACSHA256(key))
{
return checksum == Convert.ToBase64String(hmac.ComputeHash(value));
}
}
我不知道在这个框架内还有什么更好的。为数组或常规ICollection实现编写一个专门的SequenceEqual运算符并不难,因为它首先检查长度是否相等。。。但是考虑到散列很短,我就不担心了。如果你担心SequenceEqual的时间,你可以用这样的东西来代替它:
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = System.Text.Encoding.UTF8.GetBytes(secret);
byte[] value = System.Text.Encoding.UTF8.GetBytes(data);
byte[] checksum_bytes = System.Text.Encoding.UTF8.GetBytes(checksum);
using (var hmac = new HMACSHA256(key))
{
byte[] expected_bytes = hmac.ComputeHash(value);
return checksum_bytes.SequenceEqual(expected_bytes);
}
}
public static bool CompareArraysExhaustively(byte[] first, byte[] second)
{
if (first.Length != second.Length)
{
return false;
}
bool ret = true;
for (int i = 0; i < first.Length; i++)
{
ret = ret & (first[i] == second[i]);
}
return ret;
}
checksum_bytes.Zip( expected_bytes, (a,b) => a == b ).Aggregate( true, (a,r) => a && r );
这将返回与SequenceEquals相同的结果,但在给出答案之前始终检查每个元素,这将减少通过计时攻击暴露任何内容的机会。如果您担心SequenceEquals的计时,您可以始终使用以下内容替换它:
static bool VerifyIntegrity(string secret, string checksum, string data)
{
// Verify HMAC-SHA256 Checksum
byte[] key = System.Text.Encoding.UTF8.GetBytes(secret);
byte[] value = System.Text.Encoding.UTF8.GetBytes(data);
byte[] checksum_bytes = System.Text.Encoding.UTF8.GetBytes(checksum);
using (var hmac = new HMACSHA256(key))
{
byte[] expected_bytes = hmac.ComputeHash(value);
return checksum_bytes.SequenceEqual(expected_bytes);
}
}
public static bool CompareArraysExhaustively(byte[] first, byte[] second)
{
if (first.Length != second.Length)
{
return false;
}
bool ret = true;
for (int i = 0; i < first.Length; i++)
{
ret = ret & (first[i] == second[i]);
}
return ret;
}
checksum_bytes.Zip( expected_bytes, (a,b) => a == b ).Aggregate( true, (a,r) => a && r );
这会返回与SequenceEquals相同的结果,但在给出答案之前总是检查每个元素,这会减少通过计时攻击泄露任何信息的机会。我认为他的问题是,如果差异在哈希中出现的较早,SequenceEqual返回false的速度会更快,如果差异出现的较晚,则返回false的时间会更长。好的,他可以把它改成i=0;i