从密码字符串派生加密密钥和IV时,可以使用密码的SHA1哈希作为盐吗?

我正在使用Rfc2898DeriveBytes从用户提供的字符串密码安全地生成加密密钥和初始化向量,以便与对称加密一起使用(例如AesManaged)。

我将密码的SHA1哈希作为盐参数提供给Rfc2898DeriveBytes 。 这可以吗? 如果没有,那么我应该从哪里获取盐? 解密时我需要相同的盐,对吧? 所以我必须将它存储在未加密的地方 – 不安全。 如果我必须安全地存储它,那么它只是成为另一个“密码”,不是吗?

 void SecureDeriveKeyAndIvFromPassword(string password, int iterations, int keySize, int ivSize, out byte[] key, out byte[] iv) { // Generate the salt from password: byte[] salt = (new SHA1Managed()).ComputeHash(Encoding.UTF8.GetBytes(password)); // Derive key and IV bytes from password: Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(password, salt, iterations); key = derivedBytes.GetBytes(keySize); iv = derivedBytes.GetBytes(ivSize); } 

我已经看到使用恒定(硬编码)盐,我看到人们抱怨它。 我认为从密码中获取盐会更好,但我不确定这是一个最佳解决方案。

不久,我有一个需要加密的文件,以及用户输入的密码字符串。 如何正确使用Rfc2898DeriveBytes来获取安全加密密钥和IV?

谢谢。

编辑:

谢谢你的回答。 我现在明白,盐的主要(也许只是?)目的是使彩虹表的生成变得不可能 – 你不能预先生成“P @ $$ w0rd”的散列,因为它将为每个可能的散列提供不同的散列盐值。 我完全理解这一点,但是……这与对称加密真的相关吗? 我不是把哈希存储在任何地方吗? 因此,即使攻击者拥有所有可能的密码组合的彩虹表,他也做不了多少,对吧?

所以,我现在的问题是:与使用密码派生(或甚至硬编码)盐相比, 在使用对称加密算法 (如AesManaged of .NET) ,在每次加密操作中使用随机盐是否有任何优势?

对于每个密码 ,salt应该是唯一的 ,这意味着为要散列的每个密码创建一个随机密码。 salt 不是秘密,可以使用您计算的哈希值存储纯文本。

盐的想法是,攻击者不能使用预先构建的rainbowtable来获取密码。 他必须分别为每个密码构建这样的彩虹表,这没有意义。 在您找到匹配项之前,它更容易暴力破解。

在MSDN中有一个例子,其中盐来自操作系统随机源 。 这是你能做的最好的事情,为了得到一个安全的盐,不要从你的密码中拯救它。

盐旨在通过使每个目标的行为不同来防止多目标攻击。 彩虹表只是多目标攻击的一个特定化身,其中计算工作在获得目标之前就已消耗掉。

在某些情况下,多目标攻击是适用的,但彩虹表不适用。

例如:假设您正在使用具有语义安全性的经过身份validation的加密方案,例如具有唯一随机数的AES-GCM。 现在,您已获得使用不同密码加密的一百万条不同消息。

如果您不使用salt,要检查密码是否适用于其中任何一个,攻击者需要一次KDF操作和一百万次解密操作。 如果使用salt,则攻击者需要100万次KDF操作和100万次解密操作。 由于KDF与解密相比较慢,因此对第一种方案的攻击比对第二种方案的攻击要快得多。

我真的不知道什么是Rfc2898DeriveBytes但我可以告诉你以下内容:盐不必担保。 现在,你说你见过人们抱怨盐的硬编码,恒定值,以及谁说这是正确的。 盐应该是随机值,永远不是常数,否则它的目的就会被打败。

你明白用的是什么盐吗? 你显然没有。 使用哈希作为盐是一个坏主意,因为密码X将始终用相同的值Y加盐,再次,打败它的目的。

人们不喜欢硬编码的盐,因为项目的所有开发人员都可以访问它们(在开源项目或逆向工程的情况下可能是公共访问者)。 然后,攻击者可以为您的特定盐计算彩虹表并开始攻击您的系统。

盐值的一个很好的选择是:

  • 每次检查密码时都可用
  • 密码检查之间不会更改
  • 每个(或大多数)密码计算都不同

如果用户名不能改变,那么用户名将是一个不错的选择。 或者,在第一次创建用户并将其作为salt存储时,生成完全随机的值,以及数据库中的用户数据。

其他人已经解释了盐的目的,以及为什么它可以成为公共信息。

您问题的答案的另一部分: 不要从密码本身派生盐。 这与在Ashley Madison黑客攻击后最终暴露数百万密码的编程失误非常类似。

问题在于,当您使用密码生成salt时,您实际上是以第二种,更容易破解的forms提供密码。 攻击者可以完全忽略PBKDF2的输出,并简单地反转盐本身。 仅受SHA1保护,已经破坏。

在Ashley Madison,错误类似。 密码使用bcrypt存储在主数据库中,并被认为是安全的。 但后来有人发现许多帐户的密码实际存储了两次,而第二个拷贝只受MD5保护。