views:

84

answers:

2

I am taking over a system that a previous developer wrote. The system has an administrator approve a user account and when they do that the system uses the following method to hash a password and save it to the database. It sends the unhashed password to the user. When the user logs in the system uses the exact same method to hash what the user enters and compares it to the database value. We've run into a couple of times when the database entry doesn't match the user's entry whey they should. So it appears that the method isn't always hashing the value the same. Does anyone know if this method of hashing isn't reliable and how to make it reliable? Thanks.

    private string HashPassword(string password)
    {
        string hashedPassword = string.Empty;

        // Convert plain text into a byte array.
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(password);

        // Allocate array, which will hold plain text and salt.
        byte[] plainTextWithSaltBytes =
                new byte[plainTextBytes.Length + SALT.Length];

        // Copy plain text bytes into resulting array.
        for(int i = 0; i < plainTextBytes.Length; i++)
            plainTextWithSaltBytes[i] = plainTextBytes[i];

        // Append salt bytes to the resulting array.
        for(int i = 0; i < SALT.Length; i++)
            plainTextWithSaltBytes[plainTextBytes.Length + i] = SALT[i];

        // Because we support multiple hashing algorithms, we must define
        // hash object as a common (abstract) base class. We will specify the
        // actual hashing algorithm class later during object creation.
        HashAlgorithm hash = new SHA256Managed();

        // Compute hash value of our plain text with appended salt.
        byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);

        // Create array which will hold hash and original salt bytes.
        byte[] hashWithSaltBytes = new byte[hashBytes.Length +
                                            SALT.Length];
        // Copy hash bytes into resulting array.
        for(int i = 0; i < hashBytes.Length; i++)
            hashWithSaltBytes[i] = hashBytes[i];

        // Append salt bytes to the result.
        for(int i = 0; i < SALT.Length; i++)
            hashWithSaltBytes[hashBytes.Length + i] = SALT[i];

        // Convert result into a base64-encoded string.
        hashedPassword = Convert.ToBase64String(hashWithSaltBytes);

        return hashedPassword;
    }
+1  A: 

If the procedure doesn't use any random decision making (that is, it is completely deterministic), and the implementations of used algorithms are the same (and they should be - SHA256 is supposed to act exactly the same everywhere, and the same goes for Base64 strings), then it is very unlikely that the algorithm itself "isn't hashing the value the same".

If you cannot reproduce the error (meaning: find some value which always produces one hash when hashed on server, and another when hashed by the client), you should make sure that the values are transmitted and recieved right. Maybe the client got the unhashed password scrambled? Maybe the server is receiving corrupted data from the client? maybe the data in the server database itself has somehow changed? Make sure that every transaction is validated, i.e. that the user cannot recieve a corrupted password.

M.A. Hanin
+2  A: 

This function do hashing with salt. This is a techique to make sure it yield different hash for the same password and make table lookup much harder.

The hash is the same only if you have the same salt value.

see wikipedia http://en.wikipedia.org/wiki/Salt_%28cryptography%29 for detail on this technique.

Quoting http://msdn.microsoft.com/en-us/magazine/cc164107.aspx :

To slow down the attack, use salt. Salt is a way to season the passwords before hashing them, making the attacker's precomputed dictionary useless. Here's how it's done. Whenever you add an entry to the database, you calculate a random string of digits to be used as salt. When you want to calculate the hash of Alice's password, you look up the salt value for Alice's account, prepend it to the password, and hash them together. The resulting database looks like this:

<users>
  <user name='Alice' salt='Tu72*&' password='6DB80AE7...'/>
  <user name='Bob'   salt='N5sb#X' password='096B1085...'/>
  <user name='Fred'  salt='q-V3bi' password='9118812E...'/>
</users>

Note that now there is no way to tell that Bob and Fred are using the same password. Note that the salt itself isn't a secret.

J-16 SDiZ