【发布时间】:2011-12-14 16:14:35
【问题描述】:
从下面列出的链接阅读文章后:
http://news.ycombinator.com/item?id=910203
我现在正在尝试证明和理解为什么下面列出的哈希是不安全的,程序员不应该练习。
H(k || m) --> SHA1("secret-key" + "name=bob,withdraw=$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 !");
}
有人可以通过提供一个指定的示例来指导我,我可以散列、理解和证明作者在文章中对这两种散列方法的主张。提前感谢您提供的任何帮助。
【问题讨论】:
-
回复:“我在 C# 中编写了一个简单的哈希函数,试图证明作者声称的内容,但不知何故,无论我添加/填充或在消息的后面/前面添加什么,我似乎都无法做到这一点” ——用简单的语言向我们准确解释您认为作者所声称的内容。您可能无法证明作者的主张,因为您没有正确理解该主张。您的代码似乎与所提出的声明没有任何关系。
-
感谢您的意见。我实际上正在使用算法,在阅读了这篇文章后,我正在考虑使用 HMAC,因为现在我正在使用的 2 算法是不安全的?因此,我编写了上面列出的一个简单的 c 语言代码。据我了解,在不知道密钥的情况下,攻击者可以通过某种方式获得身份验证,这就是我想要证明的。总而言之,我试图理解并证明为什么使用这两种方法是不安全的?
-
来自 Wiki 由于算法的块和迭代结构以及没有额外的最终步骤,所有 SHA 函数都容易受到长度扩展和部分消息冲突攻击。 [9]这些攻击允许攻击者通过扩展消息并在不知道密钥的情况下重新计算哈希来伪造仅由密钥散列 - SHA(message | | key) 或 SHA(key | | message) 签名的消息。防止这些攻击的最简单改进是哈希两次 - SHAd(message) = SHA(SHA(0b | | message)) (0b - 零块,长度等于哈希函数的块大小)。任何 expln ?
标签: c# hash cryptography sha