6

我有一条消息要传递给自己,该消息将受到中间人攻击。正因为如此,我担心在我发送消息和接收回消息之间保持消息的完整性。

应该假设,一旦我将消息发送给自己,将来我将无法获得有关所发送消息的任何信息。该消息是完全独立的。

为此,我知道应该在发送消息之前对消息内容进行哈希处理并比较哈希值,在我发送消息之后,如果它们不同,则表明消息已被篡改。

当然,如果中间人知道哈希实际上只是消息内容的哈希,那么由于消息是自包含的,他可以创建新内容并应用相同的哈希算法的内容。

问题是,在生成哈希时,我应该将消息内容随机化到多长?什么时候达到收益递减点?

在这种情况下,我有一组键/值对。为此,我知道我必须采取的步骤是:

  1. 在消息中添加盐。盐是世界其他地方的秘密。它在散列之前附加到消息的内容。
  2. 在生成哈希之前以一致的方式对键/值对进行排序。
  3. 虽然不直接相关,但将在散列之前将时间戳添加到每条消息的内容中,以防止重放攻击。

这些是我正在考虑的可选步骤:

  1. 在我订购之前转换钥匙。我考虑过颠倒它们,然后按计数/键排序。
  2. 使用分隔键/值对的分隔符(用于键/值的分隔符和对的分隔符)。

笔记

这里不需要消息隐私,所以我不是在寻找加密。这些值必须以纯文本形式传输。

最后,我应该避免哪些哈希算法?


细节

我有一个 ASP.NET MVC 站点,我有一个控制器来处理输入验证和持久性。

如果(基于启发式,哪个并不重要)输入被确定为自动垃圾邮件尝试,IDictionary<string, string>则使用输入值创建一个模型,并将 ViewResult 发送到一般 CAPTCHA 页面。

在该视图中,在包含 CAPTCHA 控件的表单中,IDictionary<string, string>将在隐藏的输入字段中写入内容,并且表单的操作将与内容最初发布到的操作相同。这样,MVC 可以在重新提交表单时获取这些值。

正因为如此,我无法加密键/值对(或者我可以而且应该告诉我为什么以及如何加密!)。

当然,我需要再添加一个值,它包含经过哈希处理的消息内容。如果该值存在,则控制器将检查消息完整性是否得到维护,如果有,则允许持久化输入。

解决方案

我选择使用 System.Security.Cyrptography.Pkcs 命名空间中的 SignedCms 类,它代表 CMS/PKCS #7 消息的签名和验证。

为了详细说明,我使用 MAKECERT.EXE 创建了一个自行颁发的证书,然后在我的代码中,我使用此处的示例对数据进行数字签名:

http://blogs.msdn.com/shawnfa/archive/2006/02/27/539990.aspx

现在,应该确保导出的私钥上的密码安全,以及服务器上的安全性,这使得编程变得不那么重要了。

我必须为重放攻击的时间戳添加一个额外的密钥,但这不会太难。

答案归于 Kalium,不是因为他最初的帖子,而是因为他的后续评论指出了数字签名的方向,最终我发现了如何在 .NET 中使用它们。

感谢所有做出贡献的人。

4

5 回答 5

6

我认为 PGP/GPG 是你想要的。

于 2009-04-02T17:42:20.373 回答
2

允许您的应用程序验证其自己的消息未被篡改的最直接的方法是使用带密钥的散列消息身份验证代码。该消息以明文形式发送,但它还包含一个散列以防止篡改。哈希取决于消息内容和密钥。中间的人在不知道密钥的情况下无法在更改的消息上伪造散列。由于您的应用程序同时创建和验证消息,它永远不需要透露密钥。

我特别推荐 RFC-2104 http://www.ietf.org/rfc/rfc2104.txt中描述的实现,因为它已经过仔细考虑以避免大多数可能的陷阱。

如果消息还必须由不受信任的方验证真实性,那么您应该使用数字签名方案。

.Net 库中可能对这两者都有一些支持。Miles 提供了(作为评论)一个指向 MSDN 网页的链接,该链接用于使用 SHA1 哈希实现键控 HMAC 的 .Net 库函数:http: //msdn.microsoft.com/en-us/library/system.security。密码学.hmacsha1.aspx

于 2009-04-02T18:22:11.357 回答
1

你想要一个数字签名的消息。使用 GPG,您可以在加密的情况下签署消息。但是没有人能够篡改它,因为他们无法生成散列——只有你可以,因为散列使用了你的私钥

于 2009-04-02T17:48:00.970 回答
0

您可能应该对消息进行数字签名(因此 Kalium 推荐的 PGP/GPG 作为一个选项是相关的)。您可以创建的任何纯哈希都可以被攻击者重新创建。数字签名 - 使用您的私人签名密钥,以便您的公钥可用于验证它 - 是解决方案。其他任何事情都是徒劳的。

于 2009-04-02T17:48:01.173 回答
0

假设您不能通过“安全”通道(即散列)传递任何信息,您可以这样做:

  1. 散列消息,然后使用私钥对散列进行签名。在消息中包含签名的哈希。
  2. 当您收到消息时,使用公钥解密签名的散列并验证它是否与消息的实际散列匹配。

攻击者将无法“伪造”消息,因为他们需要拥有您的私钥才能加密他们的新哈希。

正如其他人所提到的,这只是普通的数字签名,可以由 PGP/GPG 之类的东西处理

于 2009-04-02T17:49:33.477 回答