阅读下面链接中的文章后:
http://news.ycombinator.com/item?id=910203
我现在正在努力证明和理解为什么下面列出的哈希是不安全的,不应该由程序员练习。
H(k || m) - > SHA1(“秘密密钥”+“名称= bob,撤回= 200美元”)
H(m || k) - > SHA1(“name = bob,withdraw = $ 200”+“secret-key”)
根据文章所述,第一个例子完全是致命的。 SHA1(以及MD5和许多其他哈希)是共享一个名为Merkle-Damgaard的通用设计的机器,这意味着它们以块长度块处理消息,并使用这些块来置换内部状态。输出SHA1是该状态的“最终”内容。但实际上没有什么能够“完成”SHA1状态;如果您在线上看到SHA1值,您可以使用附加数据继续启动Merkle-Damgaard机器。 这意味着您可以使用任意数据添加到新的消息中,这些数据会显示为真实的。这种攻击非常容易实施;它需要大约20行Ruby代码。
第二个例子也被打破了,这是博客文章的主题。如果你在消息之后粘贴了密钥,你就无法继续使用数据驱动哈希,因为你无法猜到的秘密就在它的末尾。
我在C#中编写了一个简单的哈希函数,试图证明作者声称的内容,但无论我添加/填充或在消息的后面/前面,无论如何我都无法做到这一点。
string strRet;
// hash contains the SHA 1 value of SHA1 (key + temp)
string hash = "ce0037fbbff7a1b68b5794bd73dcc7d63338f115";
try
{
string key = "password";
string temp = "name=bob,withdraw=$200";
for (int i = 0; i < 1000; i++)
{
byte[] buffer = Encoding.ASCII.GetBytes(temp);
SHA1CryptoServiceProvider cryptoTransformSHA1 = new SHA1CryptoServiceProvider();
strRet = BitConverter.ToString(cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", "");
strRet = strRet.ToLower();
MessageBox.Show(strRet);
if (strRet.Equals(hash))
{
MessageBox.Show("Hash are equal !");
MessageBox.Show(temp);
}
temp = key + temp + "2";
}
MessageBox.Show("The End !");
}
catch (Exception)
{
MessageBox.Show("There is a Error !");
}
有人可以通过提供一个指定的示例来指导我,我可以散列,理解并证明作者在文章中对两种哈希方法的主张。提前感谢您提供的任何帮助。
答案 0 :(得分:12)
答案 1 :(得分:2)
您可以链接http://rdist.root.org/2009/10/29/stop-using-unsafe-keyed-hashes-use-hmac/,这是此声明的来源。
它说这种散列方案比它需要的要弱,而不是它几乎可以用SHA-1打破。
如果底层哈希函数有任何弱点(第一次攻击的第二个原像,第二次冲突),则此方案仅容易受到攻击。根据我的记忆,SHA-1没有发现其中任何一个的实际漏洞,而MD5在第二次攻击的背景下被打破。
由于冲突是哈希函数中最容易发现的漏洞,因此除非必要,否则最好使用不易受冲突攻击的构造。这就是推荐HMAC的原因。