我有一条信息要传递给自己,该信息可能会受到中间人攻击。因此,我担心在我发送信息和接收信息回来之间,信息的完整性是否得到保持。
应该假定一旦我把消息发送给自己,未来就不会对我提供有关所发送消息的任何信息。该消息是完全自包容的。
为此,我知道在发送消息之前应该对消息内容进行哈希处理并比较哈希值,发送消息后,如果哈希值不同,则消息已被篡改。
当然,如果中间人知道哈希实际上只是消息内容的哈希,因此由于消息是自包含的,他可以创建新的内容并将相同的哈希算法应用于内容。
问题是,在生成哈希时,我应该采取多长的步骤来随机化消息内容? 什么时候会达到收益递减点?
在这种情况下,我有一组键值对。因此,我知道我必须采取的步骤是:
- 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.
- Order the key/value pairs in a consistent manner before generating the hash.
- While not directly relevant, a timestamp is going to be added to the contents of each message before hashing, to prevent replay attacks.
这些是我正在考虑的可选步骤:
- Transforming the keys before I order them. I ve considered reversing them, then ordering by count/key.
- 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中利用它们。
感谢所有作出贡献的人。