English 中文(简体)
保持信息完整性
原标题:
  • 时间:2009-04-02 17:40:19
  •  标签:

我有一条信息要传递给自己,该信息可能会受到中间人攻击。因此,我担心在我发送信息和接收信息回来之间,信息的完整性是否得到保持。

应该假定一旦我把消息发送给自己,未来就不会对我提供有关所发送消息的任何信息。该消息是完全自包容的。

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

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

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

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

  1. Add a salt to the message. The salt is a secret to the rest of the world. It gets attached to the contents of the message before hashing.
  2. Order the key/value pairs in a consistent manner before generating the hash.
  3. While not directly relevant, a timestamp is going to be added to the contents of each message before hashing, to prevent replay attacks.

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

  1. Transforming the keys before I order them. I ve considered reversing them, then ordering by count/key.
  2. Playing with the separators that separate key/value pairs (both for the separator for the key/value and the separator for the pair).

提醒

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

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


具体细节

我有一个 ASP.NET MVC 网站,其中我有一个控制器处理输入验证和持久化。

如果(基于启发式,不重要)确定输入是自动垃圾邮件尝试,则创建一个IDictionary<string,string>模型与输入值,并向一个通用的验证码页面发送ViewResult。

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

正因为这个原因,我无法加密键/值对(或许我可以并应该这么做,告诉我为什么以及如何!)。

当然,我需要添加另一个值,其中包含了散列后的消息内容。如果有这个值,控制器将检查消息完整性是否得到维护,如果有,则允许输入被持久化。

解决方案 (jiějué fāng'àn)

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

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

将此翻译成中文:http://blogs.msdn.com/shawnfa/archive/2006/02/27/539990.aspx

现在,重要的是要保护导出的私钥的密码安全以及服务器的安全性,这使得它不再局限于编程。

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

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

感谢所有作出贡献的人。

问题回答

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

让您的应用程序验证其自己的消息未被篡改的最直接方法是使用基于密钥的哈希消息认证码。消息以明文发送,但它也包括哈希以防止篡改。哈希取决于消息内容和秘密密钥。中间人无法在不知道密钥的情况下伪造已更改的消息上的哈希。由于您的应用程序既创建又验证消息,因此不需要披露秘密密钥。

我特别推荐按照RFC-2104中描述的实现方法http://www.ietf.org/rfc/rfc2104.txt,因为它已经经过仔细思考,避免了大部分可能出现的问题。

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

很可能在 .Net 库中都有一些支持。Miles(作为评论)有用地提供了一个链接到 MSDN 网页,其中实现了使用 SHA1 哈希的键入 HMAC 的 .Net 库函数:http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx。

您想要一个数字签名的信息。使用GPG,您可以在不加密的情况下签署信息。但是,没有人能够篡改它,因为他们无法生成哈希值 - 只有您能够生成哈希值,因为哈希值使用您的私钥。

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

假设您不能通过“安全”信道传递任何信息(即哈希),下面是您可能会这样做的方法:

  1. Hash the message, then sign the hash with a private key. Include the signed hash in the message.
  2. When you get the message, use the public key to decrypt the signed hash and verify that it matches the actual hash of the message.

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

正如其他人所提到的,这只是普通的数字签名,可以通过类似于PGP/GPG的东西进行处理。





相关问题
热门标签