一旦我生成了盐并散列了密码(使用bcrypt等),最好将结果存储为数据库中的字符串或字节数组吗?这两种方式都有什么好处吗?或者这是一个更主观的决定?
答案 0 :(得分:2)
VARCHAR应该足够了。在我看来,VARCHAR数据将更易于使用并与二进制文件一起使用。
内置的ASP.NET成员资格提供程序还将散列密码存储为VARCHAR字段。
答案 1 :(得分:2)
如果使用VARCHAR,请确保字节是有效字符,或者在保存哈希值和salt之前将字节强制为ASCII。为了使数据损坏更安全,您可能希望在将它们存储在VARCHAR字段中之前对Base64或Hexadecimal中的字节进行编码。
例如,如果您存储MD5或SHA1的byte[]
输出,则byte[]
转换为文本时,某些字节值可能会被删除或替换它们不是有效的UTF-8 / Unicode。如果您使用ASCII,这不应该是一个问题,但它仍然可能导致数据损坏。
如果您不想处理Hex,可以使用框架内置的base64方法Convert.ToBase64String。
如果您使用VARBINARY并且不尝试使用和文本编码方法,则此问题不应存在,但可能会使哈希比较困难。
...请注意,如果您使用NVARCHAR
此数据仍可能发生损坏......
static void Main(string[] args)
{
var salt = "MySalt";
var password = "MyPassword";
var saltedKey = CalculateHash(salt, password);
Console.WriteLine(saltedKey);
// MySalt$teGOpFi57nENIRifSW3m1RQndiU=
var checkHash = CheckHash(saltedKey, password);
Console.WriteLine(checkHash);
// True
}
private static string CalculateHash(string saltOrSaltedKey, string password)
{
var salt =
saltOrSaltedKey.Contains('$')
? saltOrSaltedKey.Substring(0, saltOrSaltedKey.IndexOf('$') + 1)
: saltOrSaltedKey + '$';
var newKey = Encoding.UTF8.GetBytes(salt + password);
var sha1 = SHA1.Create();
sha1.Initialize();
var result = sha1.ComputeHash(newKey);
// if you replace this base64 version with one of the encoding
// classes this will become corrupt due to nulls and other
// control character values in the byte[]
var outval = salt + Convert.ToBase64String(result);
return outval;
}
private static bool CheckHash(string saltedKey, string password)
{
var outval = CalculateHash(saltedKey, password);
return outval == saltedKey;
}
答案 2 :(得分:1)
大多数md5 / sha1库返回哈希base64编码,在这种情况下varchar就足够了