C# 存储用于登录时使用的寄存器的盐

C# Store salt used for the register to use on login

我在做一些思考题。 我为我的 Xamarin.Forms 应用创建了一个 Register/Login 系统。现在,当我注册一个帐户时,我对密码进行哈希处理并添加随机盐,但我对登录做同样的事情。问题是我需要为我在寄存器中使用的密码获取完全相同的盐。

以下是创建 salt 和 hasing 的 2 个函数:

public String CreateSalt(int size)
{
    var rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
    var buff = new byte[size];
    rng.GetBytes(buff);
    return Convert.ToBase64String(buff);
}

public String GenerateSHA256Hash(String input, String salt)
{
    byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input + salt);
    System.Security.Cryptography.SHA256Managed sha256hashstring =
        new System.Security.Cryptography.SHA256Managed();
    byte[] hash = sha256hashstring.ComputeHash(bytes);

    return Convert.ToBase64String(hash);
}

这是我在注册和登录时使用的代码:

async void btnLogInClicked(object sender, EventArgs args)
{
    string username = txtUsername.Text;
    string password = txtPassword.Text;

    string salt = CreateSalt(16);
    string HashedPassword = GenerateSHA256Hash(password, salt);
    HashedPassword = HashedPassword.Replace('+', '-');
    HashedPassword = HashedPassword.Replace('/', '_');

    User user = new User
    {
        Username = username,
        Password = HashedPassword
    };

    var result =  await App.RestService.Login(user);
    if (result != null)
    {
        App.Current.MainPage = new SideMenuItems();
    }
}

我怎样才能做到这一点并且仍然为每个新生成的密码使用随机盐?

似乎每年我都必须重新学习如何正确散列密码。我就是这样做的,我会尽力在这里解释。

您的问题是每次调用 CreateSalt 时都会在用户登录时生成新的盐。如评论中所述,您需要在注册期间生成一次盐和散列,并且将它们保存到数据库中。

然后,当用户登录时,您可以从数据库中检索盐,并将其与用户输入的密码一起使用以生成哈希值。最后,您将新生成的哈希值与保存在数据库中的哈希值进行比较,以查看密码是否正确。

我建议使用慢速哈希算法而不是 SHA256 来生成哈希。 PBKDF2 将是一个不错的选择,并且作为 Rfc2898DeriveBytes class. Another popular option is bcrypt. It necessitates a third-party library in .NET, but I find it to be easy to implement (at least with Node). More general info on password hashing algorithms here.

内置于 .NET 中

最后要考虑的一件事是算法使用的迭代次数。 Rfc2898DeriveBytes class 有几个构造函数,其中一个设置了默认的 1000 次迭代,这应该足够了。迭代(或 "cost")减慢哈希函数并帮助阻止攻击。