一旦我生成了盐并对密码进行哈希处理(使用 bcrypt 等),最好将结果作为字符串或字节数组存储在数据库中?这两种方式有什么好处吗?还是更主观的决定?
问问题
3037 次
3 回答
3
如果您使用 VARCHAR,请确保字节是有效字符或在保存哈希和盐之前将字节强制为 ASCII。为了更安全地避免数据损坏,您可能希望在将字节存储在 VARCHAR 字段中之前将它们编码为 Base64 或十六进制。
例如,如果您存储来自MD5或SHA1byte[]
的输出,则某些字节值在转换为文本时可能会被删除或替换,因为它们不是有效的 UTF-8/Unicode。如果您使用 ASCII,这应该不是什么大问题,但它仍然可能导致数据损坏。byte[]
如果您不想处理 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;
}
于 2010-08-02T17:25:41.577 回答
2
VARCHAR 应该足够了。在我看来,与二进制相比,VARCHAR 数据更容易使用和使用。
内置的 ASP.NET 成员资格提供程序还将散列密码存储为 VARCHAR 字段。
于 2010-08-02T17:18:45.350 回答
1
大多数 md5/sha1 库返回 base64 编码的哈希值,在这种情况下 varchar 就足够了
于 2010-08-02T18:35:34.407 回答