如何对单个文件实施密码保护?
-
09-06-2019 - |
题
我正在编写一个小型桌面应用程序,它应该能够加密数据文件并使用密码保护它(即必须输入正确的密码才能解密)。我希望加密的数据文件是独立且可移植的,因此身份验证必须嵌入到文件中(或者我是这么认为的)。
根据我所知,我有一个看起来可行且合乎逻辑的策略(这可能足以造成危险),但我不知道它是否真的是一个好的设计。所以告诉我:这疯了吗?有更好/最好的方法吗?
- 步骤1:用户输入明文密码,例如“我的难密码”
- 第2步:应用程序对用户密码进行哈希处理,并使用该值作为对称密钥来加密/解密数据文件。例如“MyDifficultPassword”-->“HashedUserPwdAndKey”。
- 步骤3:应用程序对步骤 2 中的哈希值进行哈希处理,并将新值保存在数据文件头中(即数据文件的未加密部分)并使用该值来验证用户的密码。例如“HashedUserPwdAndKey”-->“HashedValueForAuthentication”
基本上,我是从实现网站密码的常见方法(即当您不使用 OpenID 时)推断出来的,即将用户密码的(加盐)哈希值存储在数据库中,并且从不保存实际密码。但由于我使用散列用户密码作为对称加密密钥,因此我无法使用相同的值进行身份验证。因此,我再次对其进行哈希处理,基本上将其视为另一个密码,并将双重哈希值保存在数据文件中。这样,我就可以将该文件转移到另一台电脑上,只需输入密码即可对其进行解密。
那么这种设计是相当安全的,还是极其幼稚的,还是介于两者之间?谢谢!
编辑:澄清和后续问题:盐。
我认为盐必须保密才能有用,但您的答案和链接暗示情况并非如此。例如, 这个规格 由埃里克森(如下)链接说:
因此,此处定义的基于密码的密钥派生是密码、盐和迭代计数的函数,其中后两个量不需要保密。
这是否意味着我可以将盐值存储在与散列密钥相同的位置/文件中,并且仍然比散列时根本不使用盐更安全?这是如何运作的?
更多背景信息:加密的文件并不意味着与其他人共享或解密,它实际上是单用户数据。但我想将其部署在我无法完全控制的计算机上的共享环境中(例如在工作中)并且能够通过简单地复制文件来迁移/移动数据(这样我就可以在家里、不同的工作站等上使用它)。
解决方案
密钥生成
我建议使用公认的算法,例如 PBKDF2 中定义的 PKCS #5 版本 2.0 从您的密码生成密钥。它与您概述的算法类似,但能够生成更长的对称密钥以与 AES 一起使用。您应该能够找到一个为不同算法实现 PBE 密钥生成器的开源库。
文件格式
您也可以考虑使用 加密消息语法 作为文件的格式。这需要您进行一些研究,但同样有现有的库可供使用,并且它提供了与其他软件(例如支持 S/MIME 的邮件客户端)更顺利地互操作的可能性。
密码验证
关于您希望存储密码的哈希值,如果您使用 PBKDF2 生成密钥,您可以使用标准密码哈希算法(大盐,一千轮哈希),并获得不同的值。
或者,您可以计算内容的 MAC。密码上的哈希冲突更有可能对攻击者有用;内容上的哈希冲突可能毫无价值。但这会让合法接收者知道解密时使用了错误的密码。
加密盐
盐 有助于阻止预先计算的字典攻击。
假设攻击者有一个可能的密码列表。他可以对每个哈希值进行哈希处理,并将其与受害者密码的哈希值进行比较,看看是否匹配。如果列表很大,这可能需要很长时间。他不想在下一个目标上花费太多时间,因此他将结果记录在“字典”中,其中哈希值指向其相应的输入。如果密码列表非常非常长,他可以使用诸如 彩虹桌 以节省一些空间。
然而,假设他的下一个目标对他们的密码加了盐。 即使攻击者知道盐是什么,他预先计算的表也毫无价值——盐改变了每个密码产生的哈希值。他必须重新散列列表中的所有密码,将目标的盐附加到输入中。每种不同的盐都需要不同的字典,如果使用了足够的盐,攻击者将没有空间为所有盐存储字典。通过交易空间来节省时间不再是一种选择;攻击者必须回退到对他想要攻击的每个目标的列表中的每个密码进行哈希处理。
因此,没有必要对盐保密。确保攻击者没有与该特定盐相对应的预先计算的字典就足够了。
其他提示
如果您使用强哈希算法 (SHA-2) 和强加密算法 (AES),则使用此方法效果会很好。
为什么不使用支持密码保护文件的压缩库?我过去使用过包含 XML 内容的受密码保护的 zip 文件:}
是否真的需要将哈希密码保存到文件中。难道你不能只使用密码(或散列密码)和一些盐,然后用它加密文件吗?解密时只需尝试使用密码+盐来解密文件。如果用户提供了错误的密码,则解密的文件不正确。
我能想到的唯一缺点是,如果用户不小心输入了错误的密码并且解密速度很慢,他必须等待重试。当然,如果忘记密码,就无法解密文件。