System.Web.Helpers.Crypto-其中';这是盐

本文关键字:Web Helpers Crypto- 其中 System | 更新日期: 2023-09-27 18:23:35

在过去处理密码时,我总是在数据存储中分别存储salt和散列密码。今天,我想更新一些遗留代码以使用RFC2898哈希值。我偶然发现了System.Web.HelpersCrypto.Hash方法。看起来这些方法将为我完成大部分繁重的工作。有GenerateSalt()HashPassword()VerifyHashedPassword()方法。HashPassword()VerifyHashedPassword()方法不采用salt值。针对HashPassword()方法的MSDN文档中写道:

生成的哈希字节流的格式为{0x00,salt,subkey},在返回之前已进行了base-64编码。

我需要担心盐吗?文档似乎说salt将自动生成并存储在base-64编码值中?这是正确的吗?我只需要存储从HashPassword()返回的字符串?

System.Web.Helpers.Crypto-其中';这是盐

答案

所有密码都需要加盐才能安全地进行哈希。然而,在这种情况下,你是正确的;System.Web.Helpers.Crypto负责为您制作盐。你不需要创建一个。它存储在Crypto.HashPassword()返回的字符串中。

示例

你所需要做的就是这样的事情。

using System.Web.Helpers;
public void SavePassword(string unhashedPassword)
{
    string hashedPassword = Crypto.HashPassword(unhashedPassword);
    //Save hashedPassword somewhere that you can retrieve it again.
    //Don't save unhashedPassword! Just let it go.
}
public bool CheckPassword(string unhashedPassword)
{
    string savedHashedPassword = //get hashedPassword from where you saved it
    return Crypto.VerifyHashedPassword(savedHashedPassword, unhashedPassword)
}

更多信息

  • 如果你想了解更多关于Crypto类的信息,可以在这里查看
  • 这里有一个关于这门课的好博客,以及它背后的一些想法

我只想分享这篇文章:

http://forums.asp.net/t/1842429.aspx?System+Web+助手+加密+哈希密码

你好,
我一直在研究System.Web.Helpers中新的Crypto-HashPassword和VerifyMethod方法。
这两个方法都使用Salt,但它们不返回Salt,只返回Hash
我不需要盐来将其存储在数据库中吗?我是不是错过了什么
谢谢,
Miguel

当用户创建帐户时,您会生成salt,然后在调用HashPassword之前,您需要将其附加到密码中。you had 的常用口语形式然后将salt和散列后的密码存储在数据库中。当你验证凭据只需从数据库中读取salt并将其附加到调用VerifyHashedPassword之前登录的密码。BrockAllen

不确定我是否理解。。。因为在HashPassword中,Salt是方法内部生成:

Miguel

// Method in Crypto class
public static string HashPassword(string password)
{
    if (password == null)
    {
        throw new ArgumentNullException("password");
    }
    // Produce a version 0 (see comment above) password hash.
    byte[] salt;
    byte[] subkey;
    using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
    {
        salt = deriveBytes.Salt;
        subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
    }
    byte[] outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
    Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
    Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
    return Convert.ToBase64String(outputBytes);
}

布罗克艾伦2012年9月11日下午07:50

是的,忽略它——它是Rfc2898DeriveBytes的内部salt它是从密码派生的,所以它不是存储密码的上下文,因为它始终是为相同的密码。你仍然想在密码字符串级别。这样的东西:

public void CreateAccount(string username, string password)
{
    var salt = Crypto.GenerateSalt();
    var saltedPassword = password + salt;
    var hashedPassword = Crypto.HashPassword(saltedPassword);
    CreateAccount(username, salt, hashedPassword);
}
public void Verify(string username, string password)
{
    var salt = GetSaltForUserFromDatabase(username);
    var hashedPassword = GetHashedPasswordForUserFromDatabase(username);
    var saltedPassword = password + salt;
    if (Crypto.VerifyHashedPassword(hashedPassword, saltedPassword))
    {
        // valid password for this username
    }
}

这将允许您将您的salt与散列后的salt密码一起存储在数据库中。

关于使用salt进行密码哈希的其他信息,请参阅本文:https://crackstation.net/hashing-security.htm

存储密码

  1. 使用CSPRNG生成长随机盐
  2. 将salt预先添加到密码中,并使用标准加密哈希函数(如SHA256)对其进行哈希
  3. 将salt和hash都保存在用户的数据库记录中

验证密码

  1. 从数据库中检索用户的salt和hash
  2. 将salt预先设置为给定的密码,并使用相同的哈希函数对其进行哈希
  3. 将给定密码的哈希与数据库中的哈希进行比较。如果它们匹配,则密码是正确的。否则,密码不正确

加密类的源代码:

http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Helpers/Crypto.cs