我正在编写一个小桌面应用,应该能够加密数据文件并用密码保护它(即必须输入正确的密码才能解密)。我希望加密数据文件是自包含和可移植的,因此必须将身份验证嵌入到文件中(或者我假设)。
我有一个看似可行且基于我所知道的逻辑(这可能只是危险)的策略,但我不知道它是否真的是一个好的设计。那么告诉我:这是疯了吗?有更好/最好的方法吗?
基本上我是从实现网站密码的常用方法推断出来的(当你没有使用OpenID时),即在你的数据库中存储用户密码的(盐渍)哈希并且从不保存实际的密码。但由于我使用散列用户密码作为对称加密密钥,因此我无法使用相同的值进行身份验证。所以我再次哈希,基本上把它当作另一个密码处理,并将双重哈希值保存在数据文件中。这样,我可以将文件带到另一台PC,只需输入我的密码即可解密。
这个设计是否合理安全,或绝对天真,或介于两者之间?谢谢!
编辑:澄清和后续问题:盐。
我认为盐必须保密才有用,但你的答案和链接暗示情况并非如此。例如,由erickson(下面)链接的this spec说:
因此,此处定义的基于密码的密钥派生是密码,盐和迭代计数的函数,后两个数量不需要保密。
这是否意味着我可以将salt值存储在与散列键相同的位置/文件中,并且仍然比在散列时根本不使用salt时更安全?这有什么作用?
更多上下文:加密文件不应与他人共享或解密,它实际上是单用户数据。但是我想将它部署在我无法完全控制的计算机上的共享环境中(例如在工作中),并且能够通过简单地复制文件来迁移/移动数据(所以我可以在家里,在不同的地方使用它工作站等。)。
答案 0 :(得分:24)
我建议使用公认的算法,例如PKCS #5 version 2.0中定义的PBKDF2,从密码生成密钥。它与您概述的算法类似,但能够生成更长的对称密钥以与AES一起使用。您应该能够找到一个开源库,为不同的算法实现PBE密钥生成器。
您也可以考虑使用Cryptographic Message Syntax作为文件格式。这需要您进行一些研究,但同样需要使用现有的库,并且它开启了与其他软件(如支持S / MIME的邮件客户端)更顺畅地互操作的可能性。
关于存储密码哈希的愿望,如果使用PBKDF2生成密钥,则可以使用标准密码哈希算法(大盐,千轮哈希),并获得不同的值。
或者,您可以在内容上计算MAC。密码上的哈希冲突更可能对攻击者有用;内容上的哈希冲突可能毫无价值。但它可以让合法的收件人知道错误的密码被用于解密。
Salt有助于阻止预先计算的字典攻击。
假设攻击者有可能的密码列表。他可以散列每个并将其与受害者密码的哈希进行比较,看看它是否匹配。如果列表很大,这可能需要很长时间。他不希望在下一个目标上花费那么多时间,因此他将结果记录在“字典”中,其中哈希指向其相应的输入。如果密码列表非常长,他可以使用像Rainbow Table这样的技术来节省一些空间。
然而,假设他的下一个目标腌制了他们的密码。 即使攻击者知道盐是什么,他的预计算表也毫无价值 - salt会更改每个密码产生的哈希值。他必须重新哈希他列表中的所有密码,将目标的盐粘贴到输入上。每种不同的盐都需要不同的字典,如果使用足够的盐,攻击者就没有空间存储所有字典。交易空间以节省时间不再是一种选择;攻击者必须回过头来为他想要攻击的每个目标在列表中散列每个密码。
因此,没有必要保密盐。确保攻击者没有与该特定盐相对应的预先计算的字典就足够了。
答案 1 :(得分:2)
正如Niyaz所说,如果您使用强大的算法(如SHA-265和AES)进行散列和加密,这种方法听起来很合理。另外,我建议使用Salt来减少创建所有密码哈希字典的可能性。
当然,阅读Bruce Schneier的Applied Cryptography也不会错。
答案 2 :(得分:1)
如果您使用强哈希算法(SHA-2)和强加密算法(AES),那么您可以使用这种方法。
答案 3 :(得分:1)
为什么不使用支持受密码保护的文件的压缩库?我过去使用过包含XML内容的受密码保护的zip文件:}
答案 4 :(得分:0)
是否真的需要将散列密码保存到文件中。你不能只使用密码(或散列密码)和一些盐,然后用它加密文件。解密时只尝试使用密码+ salt解密文件。如果用户提供了错误的密码,则解密的文件不正确。
我能想到的唯一缺点是,如果用户意外输入了错误的密码并且解密速度很慢,他必须等待再试一次。当然,如果忘记密码,则无法解密文件。