简体   繁体   English

在数据库中存储散列密码和salt值的最佳方法 - varchar或binary?

[英]Best way to store hashed passwords and salt values in the database - varchar or binary?

Once I've generated a salt and hashed the password (using bcrypt, etc) would it be best to store the results as a string or as a byte array in the database? 一旦我生成了一个盐并散列密码(使用bcrypt等),最好将结果存储为数据库中的字符串或字节数组? Are there any benefits either way? 这两种方式都有什么好处吗? Or is it a more subjective decision? 或者这是一个更主观的决定?

VARCHAR should be sufficient. VARCHAR应该足够了。 In my opinion VARCHAR data will be easier to consume and work with vs. binary. 在我看来,VARCHAR数据将更容易消费并与二进制文件一起使用。

The built in ASP.NET membership providers also store hashed passwords as VARCHAR fields. 内置的ASP.NET成员资格提供程序还将散列密码存储为VARCHAR字段。

If you use VARCHAR either make sure the bytes are either valid characters or force the bytes to ASCII before you save the hash and salt. 如果使用VARCHAR,请确保字节是有效字符,或者在保存哈希值和salt之前将字节强制为ASCII。 To make is safer from data corruption you may want to either encode the bytes in Base64 or Hexadecimal before you store them in the VARCHAR field. 为了使数据损坏更安全,您可能希望在将它们存储在VARCHAR字段中之前对Base64或Hexadecimal中的字节进行编码。

For example, if you store the byte[] output from MD5 or SHA1 some of the byte values may be removed or replaced when the byte[] is converted to text is they are not valid UTF-8/Unicode. 例如,如果存储MD5SHA1byte[]输出,则当byte[]转换为text时,某些字节值可能会被删除或替换,因此它们不是UTF-8 / Unicode。 This should not be as much of a problem if you are using ASCII but it could still cause data corruption. 如果您使用ASCII,这不应该是一个问题,但它仍然可能导致数据损坏。

If you don't want to deal with Hex you could use this base64 method Convert.ToBase64String that is built into the framework. 如果您不想处理Hex,可以使用构建在框架中的这个base64方法Convert.ToBase64String

If you use VARBINARY and don't try to use and text encoding methods this issue should not exist, but could make comparing hashes more difficult. 如果您使用VARBINARY并且不尝试使用和文本编码方法,则此问题不应存在,但可能会使哈希比较困难。

...Note that if you use NVARCHAR this data corruption could still occur... ...请注意,如果您使用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;
}

大多数md5 / sha1库返回哈希base64编码,在这种情况下varchar就足够了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM