System.Web.Helpers.Crypto - Where's the salt?

前端 未结 2 1555
面向向阳花
面向向阳花 2021-02-01 03:21

In the past when dealing with passwords I\'ve always stored a salt and a hashed password separately in my data store. Today I was looking to update some legacy code to use a RFC

相关标签:
2条回答
  • 2021-02-01 03:24

    Answer

    All passwords need to be salted in order to hash them securely. In this case, however, you are correct. System.Web.Helpers.Crypto takes care of creating a salt for you. You don't need to create one. It is stored in the string returned by Crypto.HashPassword().

    Example

    All you need to do is something like this.

    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)
    }
    

    More Information

    • If you would like to see the source code for the Crypto class you can view it here.
    • And here is a good blog on the class and some of the ideas behind it.
    0 讨论(0)
  • 2021-02-01 03:44

    Just wanted to share this post:

    http://forums.asp.net/t/1842429.aspx?System+Web+Helpers+Crypto+HashPassword

    Hello,
    I have been looking at the new Crypto HashPassword and VerifyMethod method in System.Web.Helpers.
    Both methods use a Salt but they do not return the Salt only the Hash.
    Don't I need the Salt to store it in the database? Am I missing something?
    Thank you,
    Miguel

    ..

    You'd generate the salt when the user creates the account, and then you'd append it to the password before you call HashPassword. You'd then store that salt and the hashed password in your DB. When you validate credentials just read the salt from the DB and appends it to the password from the login before calling VerifyHashedPassword. BrockAllen

    ..

    Not sure if I understood it ... Because in HashPassword a Salt is generated inside the method:

    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);
    }
    

    ..

    BrockAllen Sep 11, 2012 07:50 PM

    Yea, ignore that -- it's an internal salt for the Rfc2898DeriveBytes and it's derived from the password so it's not a true salt in the context of storing passwords since it's consistently re-created for the same password. You will want to still do your own salt at the password string level. So something like this:

    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
        }
    }
    

    This will allow you to store your salt in the database along with the hashed salted password.

    Additional info on password hashing with salt in general from this post: https://crackstation.net/hashing-security.htm

    To Store a Password

    1. Generate a long random salt using a CSPRNG.
    2. Prepend the salt to the password and hash it with a standard cryptographic hash function such as SHA256.
    3. Save both the salt and the hash in the user's database record.

    To Validate a Password

    1. Retrieve the user's salt and hash from the database.
    2. Prepend the salt to the given password and hash it using the same hash function.
    3. Compare the hash of the given password with the hash from the database. If they match, the password is correct. Otherwise, the password is incorrect.

    Source Code for Crypto class:

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

    0 讨论(0)
提交回复
热议问题