如何为单个文件实现密码保护?

21
我正在编写一个小型桌面应用程序,该程序应能够加密数据文件并使用密码保护它(即必须输入正确的密码才能解密)。 我希望加密后的数据文件是独立且可移植的,因此认证必须嵌入到文件中(或者我这样假设)。
我有一个看起来可行并且基于我所知道的逻辑似乎是合理的策略(可能足够危险),但我不知道它是否实际上是一个好设计。 那么告诉我:这种做法是否可行? 是否有更好/最佳的方法?
步骤1:用户输入明文密码,例如“MyDifficultPassword” 步骤2:应用程序将用户密码哈希化,并使用该值作为对称密钥来加密/解密数据文件。例如,“MyDifficultPassword” -->“HashedUserPwdAndKey”。 步骤3:应用程序将步骤2中的哈希值再次哈希并将新值保存在数据文件头部(即未加密部分的数据文件中),并使用该值验证用户的密码。例如,“HashedUserPwdAndKey” -->“HashedValueForAuthentication”。
基本上,我是从实现网站密码的常见方式推断出来的(如果您没有使用OpenID的话),即在DB中存储用户密码的(加盐)哈希值并永远不保存实际密码。 但是,由于我使用了哈希的用户密码作为对称加密密钥,因此我无法在认证中使用相同的值。 因此,我再次对其进行哈希处理,基本上像处理另一个密码一样,并将双重哈希值保存在数据文件中。 这样,我可以将文件带到另一台PC并通过简单地输入我的密码来解密它。
那么,这个设计是否相当安全,或者很幼稚,或者介于两者之间? 谢谢!
编辑:澄清和关于Salt的跟进问题。我曾认为盐值必须保密才能发挥作用,但您的回答和链接表明这并非如此。例如,erickson(下面)提供的这份规范 指出:

因此,基于密码的密钥派生在这里定义为一个函数,其参数是密码、盐值和迭代计数器。其中后两个量不需要保密。

这是否意味着我可以将盐值存储在同一位置/文件中作为哈希密钥,并且仍然比使用没有盐值的哈希更安全?这是怎么做到的呢?

稍微详细说说:加密文件不打算与他人共享或解密,它是单用户数据。但我想在我无法完全控制的共享环境中部署它(例如,在工作中),并且通过简单地复制文件来迁移/移动数据(以便我可以在家中、不同的工作站等地使用它)。

5个回答

24

密钥生成

我建议使用诸如PKCS #5版本2.0定义的PBKDF2等公认算法从您的密码中生成密钥。它类似于您概述的算法,但能够生成用于AES的更长的对称密钥。您应该能够找到实现不同算法的PBE密钥生成器的开源库。

文件格式

您可能还考虑使用加密消息语法作为文件格式。这需要您进行一些研究,但是再次有现有的库可供使用,并且它打开了与其他软件(如启用S / MIME的邮件客户端)更加顺畅地交互的可能性。

密码验证

关于您想要存储密码的哈希值,如果使用PBKDF2生成密钥,则可以使用标准的密码哈希算法(大盐,千轮哈希)来实现,并获得不同的值。

或者,您可以在内容上计算MAC。密码散列冲突更有可能对攻击者有用;内容的哈希碰撞可能是毫无价值的。但它将为合法的接收者提供错误地用于解密的密码通知。

加密盐

有助于防范预先计算的字典攻击。

假设攻击者拥有一份可能的密码列表,他可以对每个密码进行哈希并将其与受害者的密码哈希进行比较,看是否匹配。如果列表很大,这可能需要很长时间。他不想在下一个目标上花费那么多时间,因此他记录了结果在一个“字典”中,其中哈希指向其相应的输入。如果密码列表非常长,他可以使用像彩虹表这样的技术来节省空间。
然而,假设他的下一个目标对密码进行了加盐。即使攻击者知道盐是什么,他预先计算的表也毫无用处——盐会改变每个密码的哈希结果。他必须重新对列表中的所有密码进行哈希,并附加目标的盐到输入中。每个不同的盐都需要一个不同的字典,如果使用足够多的盐,攻击者就没有足够的空间来存储它们所有的字典。为了节省时间而交换空间已经不再是一个选项;攻击者必须回归到为每个他想攻击的目标对列表中的每个密码进行哈希。
因此,不需要保密盐。确保攻击者没有与特定盐对应的预计算字典就足够了。

感谢提供密钥派生函数的参考。在我的概念验证测试中,我注意到哈希值的长度从未与加密函数所期望的密钥长度相同,因此我只是填充了哈希值 - 我知道必须有更好的方法,而这似乎就是它。 - Matt

2
正文:
如Niyaz所说,如果您使用强算法的高质量实现,如SHA-265AES进行哈希和加密,则这种方法听起来是合理的。此外,我建议使用Salt来降低创建所有密码哈希字典的可能性。
当然,阅读Bruce SchneierApplied Cryptography也绝不会有错。

1

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


1
为什么不使用支持密码保护文件的压缩库呢?我以前曾经使用过一个包含 XML 内容的密码保护 zip 文件 :}

1
这在提高生产力方面是个好主意,但这部分也是一个爱好/学习项目,深入研究加密库也是其中的乐趣之一。 - Matt

0
有必要将哈希密码保存到文件中吗?您不能仅使用密码(或哈希密码)加上一些盐,然后使用它加密文件吗?解密时只需尝试使用密码+盐解密文件。如果用户提供错误的密码,则解密的文件不正确。
我能想到的唯一缺点是,如果用户意外输入了错误的密码并且解密速度很慢,他必须等待再次尝试。当然,如果忘记密码,则无法解密文件。

我希望应用程序能够“知道”是否输入了正确的密码。例如,除非您输入原始密码(否则,拥有访问文件权限的恶作剧者可能会使用您不知道的密钥重新加密它),否则它不应该让您更改密码。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接