ASP.NET membership salt? ASP.NET membership salt? asp.net asp.net

ASP.NET membership salt?


What is default hash algorithm that ASP.NET membership uses? has a good discussion of their default algorithm.

I hope that helps!

Edit- The answer I was referring to is the code in the top post,

   public string EncodePassword(string pass, string salt)    {        byte[] bytes = Encoding.Unicode.GetBytes(pass);        //byte[] src = Encoding.Unicode.GetBytes(salt); Corrected 5/15/2013        byte[] src = Convert.FromBase64String(salt);         byte[] dst = new byte[src.Length + bytes.Length];        Buffer.BlockCopy(src, 0, dst, 0, src.Length);        Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);        HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");        byte[] inArray = algorithm.ComputeHash(dst);        return Convert.ToBase64String(inArray);    } 

They are combining Unicode Salt + Pass using BlockCopy

-- In response to your question:

Both algorithms are necessary and fulfill different roles...

RNG Crypto is used to generate the salt. It is basically a long string of random data. This is generated and stored on a per user basis. Typically this is done when a user is created or a password is changed.

BlockCopy is just the method they use to combine the salt with the password. The above code essentially equates to salt + password.

You aren't going to be able to recreate a salt value as it is completely random. It is, however, stored for each user by the framework.

Combining the salt with the password and hashing it using the technique above will allow you to verify users passwords using the hashed value stored by the framework.

I think we both read your question differently. The code I posted won't generate your salt, but it will let you use it in a way that is compatible with ASP.NET membership.

Sorry my explanation isn't the best- does that answer your question?


Here is how the SQLMembershipProvider generates salt.

    private string GenerateSalt() {        var buf = new byte[16];        (new RNGCryptoServiceProvider()).GetBytes(buf);        return Convert.ToBase64String(buf);   }

You can download the ASP.NET's SQL Provider code here.

The issue I was having was a development application running on IIS7. .NET 4.0 was using a different default hash algorithm than the default HashAlgorithmType for .NET 2.0.

In the "EncodePassword" sample code by Microsoft, they reference Membership.HashAlgorithmType which I believe returns the default for the framework, if it is not specified in the web.config.

I was able to get both this GenerateSalt and EncodePassword method to work for my application.

My combined code:

internal string GenerateSalt(){    byte[] buf = new byte[16];    (new RNGCryptoServiceProvider()).GetBytes(buf);    return Convert.ToBase64String(buf);}internal string EncodePassword(string pass, int passwordFormat, string salt){    if (passwordFormat == 0) // MembershipPasswordFormat.Clear        return pass;    byte[] bIn = Encoding.Unicode.GetBytes(pass);    byte[] bSalt = Convert.FromBase64String(salt);    byte[] bAll = new byte[bSalt.Length + bIn.Length];    byte[] bRet = null;    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);    if (passwordFormat == 1)    { // MembershipPasswordFormat.Hashed        HashAlgorithm s = HashAlgorithm.Create("SHA1");        // Hardcoded "SHA1" instead of Membership.HashAlgorithmType        bRet = s.ComputeHash(bAll);    }    else    {        bRet = EncryptPassword(bAll);    }    return Convert.ToBase64String(bRet);}


Here is one way of doing it. A salt is just a random number, you can use RNGCryptoServiceProvider class in the framework library to produce good random number to use as salt

private const int ITERATIONS = 10000;private const int SALT_SIZE = 32;private const int HASH_SIZE = 32;public void SaltAndHashPassword(string password, out byte[] salt,  out byte[] hash){  Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(    password,    SALT_SIZE,    ITERATIONS);  salt = rdb.Salt;  hash = rdb.GetBytes(HASH_SIZE);}