【问题标题】:How to implement password protection for individual files?如何对单个文件实施密码保护?
【发布时间】:2010-09-08 12:35:04
【问题描述】:

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

根据我所知道的,我有一个看起来可行且合乎逻辑的策略(这可能足以造成危险),但我不知道它是否真的是一个好的设计。所以告诉我:这疯了吗?有更好/最好的方法吗?

  • 第一步:用户输入明文密码,例如“我的难密码”
  • 第 2 步:应用程序对用户密码进行哈希处理,并使用该值作为对称密钥来加密/解密数据文件。例如"MyDifficultPassword" --> "HashedUserPwdAndKey"。
  • 第 3 步:应用程序对第​​ 2 步中的哈希值进行哈希处理,并将新值保存在数据文件头(即数据文件的未加密部分)中,并使用该值验证用户密码。例如"HashedUserPwdAndKey" --> "HashedValueForAuthentication"

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

那么这个设计是相当安全的,还是天真的绝望的,还是介于两者之间?谢谢!

编辑:澄清和后续问题:盐。
我认为盐必须保密才能有用,但您的答案和链接暗示情况并非如此。例如,由 erickson 链接的this spec(如下)表示:

因此,此处定义的基于密码的密钥派生是密码、盐和迭代计数的函数,其中后两个量不需要保密。

这是否意味着我可以将盐值存储在与散列密钥相同的位置/文件中,并且仍然比在散列时完全不使用盐更安全?它是如何工作的?

更多背景信息:加密文件不打算与他人共享或解密,它实际上是单用户数据。但是我想将它部署在我无法完全控制的计算机上的共享环境中(例如在工作中),并且能够通过简单地复制文件来迁移/移动数据(这样我就可以在家中使用不同的工作站等)。

【问题讨论】:

    标签: encryption cryptography passwords


    【解决方案1】:

    密钥生成

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

    文件格式

    您也可以考虑使用Cryptographic Message Syntax 作为文件格式。这需要您进行一些研究,但同样有现有的库可供使用,并且它开辟了与其他软件(例如启用 S/MIME 的邮件客户端)更顺畅地进行互操作的可能性。

    密码验证

    关于您存储密码哈希的愿望,如果您使用 PBKDF2 生成密钥,您可以为此使用标准密码哈希算法(大盐,一千轮哈希),并获得不同的值。

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

    加密盐

    Salt 有助于阻止预先计算的字典攻击。

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

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

    因此,没有必要对盐保密。确保攻击者没有与该特定盐对应的预先计算的字典就足够了。

    【讨论】:

    • 感谢密钥派生函数参考。我在概念验证测试中注意到,散列值的长度与加密函数预期的密钥长度不同,所以我只需填充散列 - 我知道必须有更好的方法,这似乎就是它.
    【解决方案2】:

    正如 Niyaz 所说,如果您使用强大算法的高质量实现,例如用于散列和加密的 SHA-265AES,则该方法听起来很合理。此外,我建议使用Salt 来减少创建包含所有密码哈希的字典的可能性。

    当然,阅读Bruce SchneierApplied Cryptography 也永远不会出错。

    【讨论】:

      【解决方案3】:

      如果您使用的是强哈希算法 (SHA-2) 和强加密算法 (AES),则可以使用这种方法。

      【讨论】:

        【解决方案4】:

        为什么不使用支持密码保护文件的压缩库呢?我过去使用过包含 XML 内容的受密码保护的 zip 文件:}

        【讨论】:

        • 这在生产力方面是一个好主意,但这部分是一个爱好/学习项目,所以挖掘加密库是一半的乐趣。
        【解决方案5】:

        是否真的需要将散列密码保存到文件中。您不能只使用带有一些盐的密码(或散列密码),然后用它加密文件。解密时只需尝试使用密码+盐解密文件。如果用户输入错误密码,则解密文件不正确。

        我认为唯一的缺点是如果用户不小心输入了错误的密码并且解密速度很慢,他必须等待重试。当然,如果忘记密码,则无法解密文件。

        【讨论】:

        • 我希望应用程序“知道”是否输入了正确的密码。例如,除非您输入原始密码,否则它不应该让您更改密码(否则,有权访问您文件的恶作剧者可能会使用您不知道的密钥重新加密它)。
        猜你喜欢
        • 2012-11-14
        • 2019-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-15
        • 2011-01-09
        • 2012-09-05
        • 1970-01-01
        相关资源
        最近更新 更多