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

TX_*_*TX_ 7 .net c# security encryption cryptography

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

我将密码的SHA1哈希值作为salt参数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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢.

编辑:

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

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

mar*_*kli 9

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

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

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