admin管理员组

文章数量:1356778

Below is HashingHelper.CreatePasswordHash() function I use to create passwordHash and passwordSalt during the Register action. I write this data into DB and when user wants to login I read from DB and call HashingHelper.VerifyPasswordHash() function to verify if ComputedHash() returned value matches the hash in DB.

On debug, I noticed while inserting passwordHash and passwordSalt into DB, it adds leading 0s for remaining space. I initially stored these two variables in DB as binary(500). Because of leading 0s it reproduces different hash and user can't login.

Example:

producedPasswordHash: {0,1,2,...,63}
storedPasswordHash: {0,1,2,...,63,0,0,....,0} (64 data and 436 leadings 0s)

public static class HashingHelper
{
    public static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
    {
        using (var hmac = new HMACSHA512())
        {
            passwordSalt = hmac.Key;
            passwordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));
        }
    }

    public static bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
    {
        using (var hmac = new HMACSHA512(passwordSalt))
        {
            var computedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));

            for (int i = 0; i < computedHash.Length; i++)
            {
                if (computedHash[i] != passwordHash[i])
                {
                    return false;
                }
            }

            return true;
        }
    }
}

What is best practice for storing such data in DB?
Should I handle this before writing to DB?
Considering possible SHA-1024 req. in future, what are preferred sizes for hash and salt in DB?

Here states that even SHA-512 is overkill but post is from 2014.

Thanks for help,

Below is HashingHelper.CreatePasswordHash() function I use to create passwordHash and passwordSalt during the Register action. I write this data into DB and when user wants to login I read from DB and call HashingHelper.VerifyPasswordHash() function to verify if ComputedHash() returned value matches the hash in DB.

On debug, I noticed while inserting passwordHash and passwordSalt into DB, it adds leading 0s for remaining space. I initially stored these two variables in DB as binary(500). Because of leading 0s it reproduces different hash and user can't login.

Example:

producedPasswordHash: {0,1,2,...,63}
storedPasswordHash: {0,1,2,...,63,0,0,....,0} (64 data and 436 leadings 0s)

public static class HashingHelper
{
    public static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
    {
        using (var hmac = new HMACSHA512())
        {
            passwordSalt = hmac.Key;
            passwordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));
        }
    }

    public static bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
    {
        using (var hmac = new HMACSHA512(passwordSalt))
        {
            var computedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(password));

            for (int i = 0; i < computedHash.Length; i++)
            {
                if (computedHash[i] != passwordHash[i])
                {
                    return false;
                }
            }

            return true;
        }
    }
}

What is best practice for storing such data in DB?
Should I handle this before writing to DB?
Considering possible SHA-1024 req. in future, what are preferred sizes for hash and salt in DB?

Here states that even SHA-512 is overkill but post is from 2014.

Thanks for help,

Share Improve this question edited Mar 31 at 12:35 Basheer Jarrah 5613 silver badges15 bronze badges asked Mar 31 at 12:25 WowDogeCodeWowDogeCode 291 silver badge7 bronze badges 6
  • 2 What's wrong with varbinary(500) along with separate salt and algorithm columns? – Charlieface Commented Mar 31 at 12:44
  • 4 First of all, you shouldn't use SHA for hashing passwords because it's not designed for that. Use bcrypt instead, which will also take care of properly salting your password hash ... – derpirscher Commented Mar 31 at 12:48
  • 1 The biggest mistake here is not using a proper password hash function (hmac-sha512 is a fast keyed hash, not a password hash). Then, it seems like you're using fixed-length columns in the DB of the wrong size. Either use variable length data structures or change the fixed length to the correct one. – Alejandro Commented Mar 31 at 12:56
  • @Charlieface So I should also store algorithm in DB? So in future I can also verify passwords hashed by older algorithms? – WowDogeCode Commented Mar 31 at 12:58
  • 1 That would probably be wise. EC alogrithms have shown that hash size is not a determinant of what alogrithm was used, so if you plan on changing algorithms then it makes sense to store it. – Charlieface Commented Mar 31 at 13:00
 |  Show 1 more comment

1 Answer 1

Reset to default 1

Based on SQL binary and varbinary docs:

Fixed-length binary data with a length of n bytes, where n is a value from 1 through 8,000. The storage size is n bytes.

Also based on the docs:

Data type Use when ...
binary the sizes of the column data entries are consistent.
varbinary the sizes of the column data entries vary considerably.
varbinary(max) the column data entries exceed 8,000 bytes.

So, you have to change the column data type to varbinary, to avoid constant allocation and leading zeros for unused bytes.

本文标签: netHow to store PasswordHash and PasswordSalt correctly in DBStack Overflow