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,
1 Answer
Reset to default 1Based 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.
varbinary(500)
along with separatesalt
andalgorithm
columns? – Charlieface Commented Mar 31 at 12:44