ValidateUser Method for Entity Framework MVC3 Razor Custom Member Provider C# Using LINQ

From my C# MVC3 Razor Custom Membership Provider article and source code, here is the code for the ValidateUser method. I welcome any suggestions for improvement.
public override bool ValidateUser(string username, string password)
{
    // PasswordFormat = Hashed
    byte[] hashedPassword = HashPassword(password.Trim());
    // NKT: LINQ to Entities does not recognize 
    // the method 'Int32 ToInt32(System.Object)' method, 
    // and this method cannot be translated into a store expression.
    int userStatus = 
        Convert.ToInt32(SSS.GlobalListValues.Enums.UserStatusCode.Active);
    using (var context = new SSSEntities())
    {
        var query =
            from u in context.UserProfiles
            where u.UserName == username &&
            u.UserPassword == hashedPassword &&
                u.UserStatusCode == userStatus
            select u;

        bool isUserFound = false;
        foreach (var user in query.Take(1))
        {
            isUserFound = true;
        }
        return isUserFound;
    }
}

[SIGNATURE]

3 Comments

  • You don't seem to be salting your password hashes, which leaves them open to a rainbow table attack:

    http://en.wikipedia.org/wiki/Rainbow_table
    http://en.wikipedia.org/wiki/Salt_%28cryptography%29

  • Well, I actually do salt my password, but all of that is handled in the HashPassword function, which I haven't included.

    The code is in the project itself.

    Did you look at the source code and find something missing with it, or are you referring to what you see here?

  • If you're salting the password in the HashPassword function, then you must be using the same salt for all passwords. Whilst an attacker would not be able to use a pre-computed rainbow table, they would only need to construct one table using your salt value to attack every password in the system.

    The recommended approach is to use a different salt for every record. That way, an attacker would need to compute a completely new set of salted hashes for each record.

    The code would look something like this:

    using (var context = new SSSEntities())
    {
    var query =
    from u in context.UserProfiles
    where u.UserName == username
    && u.UserStatusCode == userStatus
    select u;

    var user = query.SingleOrDefault();
    if (null != user)
    {
    byte[] hashedPassword = HashPassword(password.Trim(), user.PasswordSalt);

    // NB: Equality operator doesn't work with arrays.
    if (hashedPassword.SequenceEqual(user.UserPassword))
    {
    return true;
    }
    }

    return false;
    }

Comments have been disabled for this content.