从密码中导出盐-它的安全性如何?

时间:2019-03-10 15:16:07

标签: security encryption salt

我遇到以下问题: 在Java应用程序中,我想将一些配置数据存储在加密的本地文件中。该文件可能用于机密数据,例如用户凭据。

应该使用密码(并且只有密码)才能访问此文件。 现在,大多数值得信赖的人和参考实现都使用随机盐。我完全理解这是一个合理的选择。但是,如果我的应用程序终止并在以后启动,则随机盐不再可用。此应用程序是独立的,因此不能将其他数据库用作盐存储。

对于我的软件,用户只能输入密码(表示:无用户名,无盐,无喜爱的动物或肤色)。

现在我的想法是从密码中提取盐(例如,使用SHA-256的前16个字节)。

我的问题是:

  • 此实现的安全性如何?
  • 仅用密码对内容进行加密的常见方法是什么?

这个问题的目的不是什么

  • 盐储存在哪里
  • 安全算法和加密实现(当然,我自己没有实现加密)
  • 建筑方面的改进(不,我不希望使用全局数据库来存储内容)

2 个答案:

答案 0 :(得分:0)

要加密数据,需要一个密钥而不是密码。 key-derivation-functions可以从用户密码中获取密钥。

盐可以用于密码哈希,但不能用于加密数据。加密也有类似的概念,其中的随机值称为IV或Nonce,并与加密的数据一起存储。

最好的办法是

  1. 使用带有盐的密钥派生功能从密码中获取密钥。
  2. 使用生成的密钥,您可以加密数据。
  3. 在这种情况下,盐可以存储在加密的数据容器中(IV已经存在),因此不需要全局数据库。

要回答您的原始问题:从密码中派生盐会否定盐的全部用途,只是变成了更复杂的哈希函数。

答案 1 :(得分:0)

首先,如果可以的话,我强烈建议您不要设计新颖的加密格式。正确地进行操作非常困难。如果您想要一种加密格式来执行您要描述的内容,请参见JNCryptor,它是RNCryptor格式的实现。 RNCryptor格式是专门为解决此问题而设计的,因此,该规范是有关如何在不想直接使用它的情况下创建自己的格式的良好信息来源。 (我是RNCryptor的作者。)

另请参见libsodium。由于各种技术原因,它是一种比RNCryptor更好的加密格式,但是正确安装和使用它有点困难。 libsodium有several Java bindings

当您说“当然,我不是自己实现加密货币”时,这就是您正在做的。加密方案不仅仅是AES代码。决定如何以新颖的方式产生盐类是实现加密。有许多种方法可以通过简单的方式将安全原语(例如盐)组合在一起,并使它们极其不安全。这就是为什么您要使用成熟的东西。

关键要点是将盐与数据一起存储。我知道您说的不是储存盐,而是您要这样做。最简单的方法是将盐粘贴到密文的开头并将其存储。然后,您只需从标题中读取盐。同样,如果方便的话,可以将整个东西放在一个信封中。像JSON这样简单的东西:

{ "salt": "<base64-salt>",
  "data": "<base64-data>" }

这不是存储数据的最有效方法,但它简单,标准且安全。

请记住,盐不是秘密。每个人都可以读懂盐是很好的。


好的,足够正确的方法了。让我们解决您的实际问题。

您的加盐建议不是盐。它只是一个略有不同的哈希函数。麻烦的是,如果两次使用相同的密码(而不打算使用相同的密码),那么它们将具有不同的哈希值。您的方案无法达到目的。如果我采用与您相同的方法,并且选择与您相同的密码,那么哈希将相同。彩虹桌赢了。

使用固定盐而不是修改的哈希函数来解决的方法。您应该选择代表您的系统的盐。我通常喜欢反向DNS,因为它可以带来唯一性。例如:“ com.example.mygreatapp”。其他人自然会选择“ org.example.ourawesomedb”。您还可以选择一个长随机字符串,但重要的是唯一性,因此我喜欢反向DNS。 (随机字符串往往使人们认为盐是秘密,而盐不是(不是)秘密。)

这就是整个系统;只需选择一些系统专用的恒盐即可。 (如果您有用户名,则将用户名添加到盐中。这是构造确定性盐的标准方法。)

但是对于文件存储,我永远不会那样做。