我有一条消息要传递给自己,该消息将受到中间人攻击。正因为如此,我担心在我发送消息和接收回消息之间保持消息的完整性。
应该假设,一旦我将消息发送给自己,将来我将无法获得有关所发送消息的任何信息。该消息是完全独立的。
为此,我知道应该在发送消息之前对消息内容进行哈希处理并比较哈希值,在我发送消息之后,如果它们不同,则表明消息已被篡改。
当然,如果中间人知道哈希实际上只是消息内容的哈希,那么由于消息是自包含的,他可以创建新内容并应用相同的哈希算法的内容。
问题是,在生成哈希时,我应该将消息内容随机化到多长?什么时候达到收益递减点?
在这种情况下,我有一组键/值对。为此,我知道我必须采取的步骤是:
- 在消息中添加盐。盐是世界其他地方的秘密。它在散列之前附加到消息的内容。
- 在生成哈希之前以一致的方式对键/值对进行排序。
- 虽然不直接相关,但将在散列之前将时间戳添加到每条消息的内容中,以防止重放攻击。
这些是我正在考虑的可选步骤:
- 在我订购之前转换钥匙。我考虑过颠倒它们,然后按计数/键排序。
- 使用分隔键/值对的分隔符(用于键/值的分隔符和对的分隔符)。
笔记
这里不需要消息隐私,所以我不是在寻找加密。这些值必须以纯文本形式传输。
最后,我应该避免哪些哈希算法?
细节
我有一个 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 中使用它们。
感谢所有做出贡献的人。