如何对单个文件实施密码保护?
我正在编写一个小型桌面应用程序,该应用程序应该能够加密数据文件并使用密码对其进行保护(即必须输入正确的密码才能解密)。我希望加密的数据文件是自包含的并且可移植,因此必须将身份验证嵌入到文件中(或者我假设是)。
根据我所知道的,我有一个看起来可行并且看起来合乎逻辑的策略(可能刚好够危险),但是我不知道它实际上是否是一个好的设计。所以告诉我:这疯了吗?有没有更好/最好的方法呢?
- 步骤1:用户输入纯文本密码,例如" MyDifficultPassword"
- 步骤2:应用程序对用户密码进行哈希处理,并将该值用作对称密钥来加密/解密数据文件。例如" MyDifficultPassword"->" HashedUserPwdAndKey"。
- 步骤3:应用程序对步骤2中的哈希值进行哈希处理,然后将新值保存在数据文件头(即数据文件的未加密部分)中,并使用该值来验证用户的密码。例如" HashedUserPwdAndKey"->" HashedValueForAuthentication"
基本上,我是从实现网站密码的通用方法推断出来的(即,当我们不使用OpenID时),这是将用户密码的(加盐的)哈希值存储在数据库中,而从不保存实际密码。但是,由于我使用哈希用户密码作为对称加密密钥,因此无法使用相同的值进行身份验证。因此,我再次对其进行哈希处理,基本上将其像另一个密码一样对待,并将双哈希值保存在数据文件中。这样,我可以将文件带到另一台PC上,只需输入密码即可对其解密。
那么,这种设计是否合理地安全,或者绝望地天真或者介于两者之间?谢谢!
编辑:澄清和后续问题:盐。
我认为盐必须保密才能有用,但回答和联系暗示事实并非如此。例如,下面由erickson链接的规范说明如下:
Thus, password-based key derivation as defined here is a function of a password, a salt, and an iteration count, where the latter two quantities need not be kept secret.
这是否意味着我可以将盐值与哈希键存储在相同的位置/文件中,并且比哈希时完全不使用盐更安全?这是如何运作的?
还有一点背景:加密文件并不意味着要与他人共享或者解密,它实际上是单用户数据。但是我想将其部署在我无法完全控制(例如在工作中)的计算机上的共享环境中,并且能够通过简单地复制文件来迁移/移动数据(因此我可以在家中,其他地方使用工作站等)。
解决方案
回答
如果我们使用强大的哈希算法(SHA-2)和强大的加密算法(AES),则可以很好地使用此方法。
回答
为什么不使用支持密码保护文件的压缩库?过去,我曾使用包含XML内容的受密码保护的zip文件:}
回答
正如Niyaz所说,如果我们使用高质量的强大算法(例如SHA-265和AES)进行哈希和加密,这种方法听起来是合理的。另外,我建议使用Salt来减少创建所有密码哈希的字典的可能性。
当然,阅读Bruce Schneier的Applied Cryptography也不会错。
回答
密钥生成
我建议使用诸如PKCS#5版本2.0中定义的PBKDF2之类的公认算法,从密码生成密钥。它与我们概述的算法相似,但是能够生成更长的对称密钥以用于AES。我们应该能够找到一个实现不同算法的PBE密钥生成器的开源库。
文件格式
我们可能还会考虑使用加密消息语法作为文件的格式。这需要我们进行一些研究,但是仍然需要使用现有的库,这为与其他软件(如启用了S / MIME的邮件客户端)之间更流畅地互操作提供了可能性。
密码验证
关于我们希望存储密码的哈希值,如果使用PBKDF2生成密钥,则可以为此使用标准的密码哈希算法(大盐,一千次哈希),并获得不同的值。
或者,我们可以在内容上计算MAC。密码上的哈希冲突更可能对攻击者有用。内容上的哈希冲突可能毫无价值。但这将使合法接收者知道解密使用了错误的密码。
密码盐
Salt有助于阻止预先计算的字典攻击。
假设攻击者拥有一个可能的密码列表。他可以对每个哈希进行哈希处理,然后将其与受害者密码的哈希进行比较,看是否匹配。如果列表很大,这可能需要很长时间。他不想在下一个目标上花费太多时间,因此他将结果记录在"字典"中,其中哈希值指向其对应的输入。如果密码列表非常长,他可以使用诸如Rainbow Table之类的技术来节省空间。
但是,假设他的下一个目标使他们的密码变了。即使攻击者知道salt是什么,他的预计算表也毫无用处,salt会更改每个密码产生的哈希值。他必须重新哈希列表中的所有密码,并将目标的盐添加到输入中。每个不同的盐都需要使用不同的字典,如果使用了足够的盐,则攻击者将没有足够的空间来存储所有字典。节省时间的交易空间不再是一种选择;攻击者必须退回去哈希列表中要攻击的每个目标的每个密码。
因此,不必保守盐的秘密。确保攻击者没有与该特定盐对应的预先计算的字典就足够了。
回答
是否真的需要将哈希密码保存到文件中。我们不能只使用带有一些盐的密码(或者哈希密码),然后使用它来加密文件。解密时,只需尝试使用密码+ salt解密文件即可。如果用户输入了错误的密码,则解密的文件不正确。
我能想到的唯一缺点是,如果用户不小心输入了错误的密码并且解密速度很慢,则他必须等待再次尝试。当然,如果忘记了密码,则无法解密该文件。