我正在开发一个桌面应用程序,在这个应用程序中,我们处理敏感数据,我们希望用密码加密本地文件,当用户打开应用程序时,我们会问他。在大多数类似的项目中,我们看到人们存储密码的散列,以便在尝试解密所有密码之前验证密码是否有效。这暴露了一个安全问题,因为哈希可以很容易地从外部提取并强制执行。
我们要做的是在文件的开头放置一个静态文本来解密,当用户输入密码时,应用程序尝试解密该印章,如果可以的话,这将意味着密码是有效的,然后他可以继续解密文件的其余部分。
安全吗?由于我在任何地方都没有看到这种情况,所以我不确定我是否忽略了一些可能使这个系统变得脆弱的东西。
编辑:
我想重温这个问题,因为从那以后我学了很多密码学。
显然,正确的答案是“不要自己动手,用一个库来做那些知道自己在做什么的人”。
基本上,问题是在试图用密码解密一个大文件之前,如何验证密码是否正确。我今天推荐的基本方案是生成一个随机密钥,使用它加密文件,然后使用一个由强KDF(如Argon2、Scrypt、BCrypt或PBKDF2)和AEAD (如ChaCha20Poly1305、AES-GCM )生成的密钥包装它,或者如果您信任更新的算法,您可以使用Deoxys-II或Ascon之类的方法。这样,密码就可以更改,而无需重新加密文件,而且您的代码可以轻松地检查密码是否有效。这有点类似于KeePass和其他密码管理器的做法,只不过他们通常使用“常规”密码+ HMAC而不是AEAD。
博士:密码是复杂的,使用一个库。
发布于 2017-06-28 06:46:04
TL;DR:使用适当的密钥派生函数,而不是使用本地的方案。
哈希可以很容易地提取出来,并在外部强制执行。
我认为您低估了预图像攻击在现代密码哈希函数上的难度。
安全吗?由于我在任何地方都没有看到这种情况,所以我不确定我是否忽略了一些可能使这个系统变得脆弱的东西。
如果做得对,你提出的建议可能不会真的很脆弱,但它也可能不会给你买多少钱。正如以前的答案所讨论的那样,做错了事情,它可能会变得极度不安全。
基本上,当您考虑对密码进行散列时,不要只考虑您的平均密码散列函数(如MD5或SHA512 )的一轮。相反,您的第一选择应该是使用正确的基于密码的密钥推导函数。有许多这样的选择,但目前比较流行的选择似乎是PBKDF2和bcrypt,氪石越来越受欢迎。
与普通的哈希基元不同,密钥派生函数被专门设计为速度慢,并且尽量给攻击者提供尽可能少的优势,即使攻击者能够使用自定义硬件攻击用户输入的密码,即使该密码的熵相对较低。
您仍然可以存储一些指示密码是否正确的内容。例如,卢克斯通过存储主密钥的盐水加密散列来实现这一点;如果用户提供的密码没有正确地解密任何密钥插槽,那么密钥槽中的主密钥数据的解密将产生一个不正确的结果,从而产生一个不同的主密钥哈希,该散列被检测到并作为“不正确的密码短语”进行操作。请注意,在这种情况下,密码本身的散列没有存储。比较磁盘上的LUKS格式,图1 PHDR布局。
发布于 2017-06-27 21:14:07
尝试使用类似PBKDF2的方法将密码转换为密钥,然后用它对文件进行加密。PBKDF2提供了盐渍和迭代配置,使蛮力变得更加困难。
发布于 2017-06-28 01:58:46
在大多数类似的项目中,我们看到人们存储密码的散列,以便在尝试解密所有密码之前验证密码是否有效。这暴露了一个安全问题,因为哈希可以很容易地从外部提取并强制执行。
这是一个不正确的解决方案,但并不是因为你给出的原因。事实上,任何密码是唯一秘密的加密方案都允许攻击者进行和测试密码猜测。此问题只能通过要求密码之外的其他内容才能避免。
我们要做的是在文件的开头放置一个静态文本来解密,当用户输入密码时,应用程序尝试解密该印章,如果可以的话,这将意味着密码是有效的,然后他可以继续解密文件的其余部分。
这是有缺陷的,因为您试图使用加密来检查密码的有效性,但是加密并不提供这样的保证。
这里的正确解决方案相当复杂,而且很容易出错。我能说什么密码很难。要加密文件,以下是一个不完整的步骤大纲:
要解密文件:
提高安全性的一种方法是将盐类存储在文件之外的其他地方,攻击者不太可能找到这些盐类。例如,1 password密码管理器将salt称为“秘密钥匙”,它将salt与加密的密码库文件分开存储在设备中。在线同步传输密文,但用户必须在设备之间手动复制密钥。
https://security.stackexchange.com/questions/162914
复制相似问题