关于加密:如何对单个文件实施密码保护?

How to implement password protection for individual files?

我正在编写一个小型桌面应用程序,它应该能够加密数据文件并用密码保护它(即必须输入正确的密码才能解密)。我希望加密的数据文件是独立的和可移植的,因此必须将身份验证嵌入到文件中(或者我假设是这样)。

我有一个看起来可行的策略,并且基于我所知道的(这可能只是足够危险的),但我不知道它是否是一个好的设计。告诉我:这疯了吗?有更好/最好的方法吗?

  • 步骤1:用户输入纯文本密码,例如"myDifficultPassword"
  • 步骤2:app散列用户密码,并使用该值作为对称密钥来加密/解密数据文件。例如,"MyDifficultPassword"-->"HashEduerPwdAndKey"。
  • 步骤3:app散列步骤2中的散列值,并将新值保存在数据文件头(即数据文件的未加密部分)中,并使用该值验证用户密码。例如,"hashedUserPwdAndKey"-->"hashedValueforAuthentication"

基本上,我是从实现网站密码的常用方法(即,当您不使用openid时)推断出来的,这是将用户密码的(salted)散列存储在数据库中,而从不保存实际密码。但由于我使用哈希用户密码作为对称加密密钥,所以不能使用相同的值进行身份验证。所以我再次散列它,基本上就像处理另一个密码一样,并将双重散列值保存在数据文件中。这样,我就可以把文件带到另一台电脑上,只需输入密码就可以解密。

那么,这种设计是合理安全的,还是毫无希望的幼稚,或者介于两者之间?谢谢!

编辑:澄清和后续问题回复:盐。我认为盐必须保密才能有用,但你的答案和链接暗示情况并非如此。例如,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.

这是否意味着我可以将salt值存储在与哈希键相同的位置/文件中,并且仍然比哈希时完全不使用salt更安全?这是怎么回事?

更多的上下文:加密文件并不意味着与其他人共享或解密,它实际上是单用户数据。但是我想把它部署在一个共享的环境中,在我无法完全控制的计算机上(例如在工作时),并且只需复制文件就能迁移/移动数据(这样我就可以在家里、不同的工作站上使用它等)。


密钥生成

我建议使用已识别的算法(如pkdcs 5版本2.0中定义的pbkdf2)从密码生成密钥。它类似于您概述的算法,但能够生成较长的对称密钥,用于AES。您应该能够找到一个开源库,它为不同的算法实现PBE密钥生成器。

文件格式

您还可以考虑使用加密消息语法作为文件的格式。这将需要您进行一些研究,但同样也有现有的库可供使用,并且它为与其他软件(如支持S/MIME的邮件客户端)的交互操作提供了可能。

密码验证

关于您存储密码散列的愿望,如果您使用pbkdf2生成密钥,那么可以使用标准的密码散列算法(big salt,1000轮散列)来实现,并获得不同的值。

或者,您可以在内容上计算一个mac。密码上的哈希冲突更有可能对攻击者有用;内容上的哈希冲突可能毫无价值。但是它可以让合法的接收者知道用于解密的密码是错误的。

密码盐

salt有助于阻止预计算字典攻击。

假设攻击者有一个可能的密码列表。他可以散列每个密码,并将其与受害者密码的散列进行比较,看看是否匹配。如果列表很大,这可能需要很长时间。他不想在下一个目标上花费那么多时间,所以他将结果记录在一个"字典"中,其中散列指向对应的输入。如果密码列表非常长,他可以使用彩虹表之类的技术来节省一些空间。

但是,假设他的下一个目标使用了他们的密码。即使攻击者知道salt是什么,他预先计算的表也是毫无价值的—salt会更改每个密码产生的哈希值。他必须重新散列列表中的所有密码,将目标的salt附加到输入中。每种不同的salt都需要一个不同的字典,如果使用足够的salt,攻击者将没有足够的空间为它们存储字典。交易空间以节省时间不再是一个选项;攻击者必须返回到散列他想要攻击的每个目标的列表中的每个密码。

所以,没有必要保守盐的秘密。确保攻击者没有与特定salt对应的预计算字典就足够了。


正如Niyaz所说,如果您使用诸如sha-265和aes之类的强算法的高质量实现进行哈希和加密,那么这种方法听起来是合理的。另外,我建议使用salt来减少创建所有密码散列的字典的可能性。

当然,阅读布鲁斯施耐尔的应用密码学也从来没有错。


为什么不使用支持密码保护文件的压缩库?我以前使用过一个受密码保护的zip文件,其中包含XML内容:


如果您使用的是强哈希算法(sha-2)和强加密算法(aes),那么您可以很好地使用这种方法。


是否确实需要将哈希密码保存到文件中?你不能只使用密码(或哈希密码)加一些盐,然后用它加密文件吗?解密时,只需尝试用密码+salt来解密文件。如果用户提供了错误的密码,则解密的文件不正确。

我能想到的唯一缺点是,如果用户意外地输入了错误的密码,并且解密速度很慢,他必须等待再试一次。当然,如果忘记了密码,就无法解密文件。