locked
SimpleMembership password hash compute RRS feed

  • Question

  • User1951653217 posted

    Hi, i'm using simple membership provider. I would like to replace it with custom membership provider. Bu i have to compute password for validate user from Db. i researched and found  a method for this but, password doesn't match with DB values. Method generates smaller length and wrong passwords hash. And in webpages_Membership table PasswordSalt field always blank string? How can i hash password same as db and simplemembership. thanks for your help

    method value for 123456
    btWDPPNShuv4Zit7WUnw10K77D8=

    db value for 123456 
    ABtYn2fEmwcXXMp7aGDLetIx0TmdD4RwSrFyFNd2+9NqdwnVo1+fdn0fmAjH7enG+w==

       public string EncodePassword(string pass, string saltBase64)
            {
                byte[] bytes = Encoding.Unicode.GetBytes(pass);
                byte[] src = Convert.FromBase64String(saltBase64);
                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);
            }



    Thursday, November 20, 2014 2:34 AM

Answers

All replies

  • User-821857111 posted

    The easiest thing to do is to use the Crypto.HashPassword method from System.Web.Helpers. It's the method that the SimpleMembershipProvider uses. Then you can use the Crypto.VerifyHashedPassword method to test what the user submits. 

    The salt is combined with the hashed password, which is why the membership table's Salt column is empty.

    http://www.mikesdotnetting.com/article/200/the-simplemembershipprovider-secure-passwords-and-the-crypto-helper

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, November 20, 2014 3:01 AM
  • User1951653217 posted

    Thank you very much Mikes,

    I thought we could query the password from database . But now i realized this way is not correct . Maybe someone can need  this methods below. Hash method generates diffirent password for every call. But all of that values return true on VerifyHashedPassword for examples 2 password below generated for 123456 and return true on VerifyHashedPassword.

    So We cant do select * from  [webpages_Membership] where password=@hashedpass
    We have to select password field of user first and we can verify with method below.

    AP6q4Fmo/I4D/G1jQzFEJnSP69DMF3BB3mNfUI26ATWj8TLmlIPcBBeegEVmUKkfuw==
    ABtYn2fEmwcXXMp7aGDLetIx0TmdD4RwSrFyFNd2+9NqdwnVo1+fdn0fmAjH7enG+w==

       private const int PBKDF2IterCount = 1000; // default for Rfc2898DeriveBytes
              private const int PBKDF2SubkeyLength = 256 / 8; // 256 bits
              private const int SaltSize = 128 / 8; // 128 bits
         
            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);
            }
    
            public bool ByteArraysEqual(byte[] b1, byte[] b2)
            {
                if (b1 == b2) return true;
                if (b1 == null || b2 == null) return false;
                if (b1.Length != b2.Length) return false;
                for (int i = 0; i < b1.Length; i++)
                {
                    if (b1[i] != b2[i]) return false;
                }
                return true;
            }
    
            // hashedPassword must be of the format of HashWithPassword (salt + Hash(salt+input)
            public  bool VerifyHashedPassword(string hashedPassword, string password)
            {
                if (hashedPassword == null)
                {
                    throw new ArgumentNullException("hashedPassword");
                }
                if (password == null)
                {
                    throw new ArgumentNullException("password");
                }
    
                byte[] hashedPasswordBytes = Convert.FromBase64String(hashedPassword);
    
                // Verify a version 0 (see comment above) password hash.
    
                if (hashedPasswordBytes.Length != (1 + SaltSize + PBKDF2SubkeyLength) || hashedPasswordBytes[0] != 0x00)
                {
                    // Wrong length or version header.
                    return false;
                }
    
                byte[] salt = new byte[SaltSize];
                Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, SaltSize);
                byte[] storedSubkey = new byte[PBKDF2SubkeyLength];
                Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, PBKDF2SubkeyLength);
    
                byte[] generatedSubkey;
                using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, PBKDF2IterCount))
                {
                    generatedSubkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
                }
    
                return ByteArraysEqual(storedSubkey, generatedSubkey);
            }
    
            public ContentResult GetHashedPassword()
            {
                //return Content(HashPassword("123456").ToString());
                return Content(VerifyHashedPassword("AIfmAuqYq7h1elmpJ0kAKexvCbOH64uU4ofipNT6jYUT17rmQLReUks9wFAkanJ5iQ==", "123456").ToString());
            }

    Thursday, November 20, 2014 4:34 AM