Лучший способ хранить хешированные пароли и солт-значения в базе данных - varchar или бинарный? - PullRequest
2 голосов
/ 02 августа 2010

После того, как я сгенерировал соль и хешировал пароль (используя bcrypt и т. Д.), Было бы лучше сохранить результаты в виде строки или байтового массива в базе данных? Есть ли какие-либо преимущества в любом случае? Или это более субъективное решение?

Ответы [ 3 ]

2 голосов
/ 02 августа 2010

Если вы используете VARCHAR, либо убедитесь, что байты являются допустимыми символами, либо принудительно передайте байты в ASCII, прежде чем сохранять хеш и соль.Чтобы защитить данные от повреждения, вы можете захотеть либо кодировать байты в Base64, либо в шестнадцатеричном формате, прежде чем сохранять их в поле VARCHAR.

Например, если вы сохраняете вывод byte[] из MD5 или SHA1 некоторые байтовые значения могут быть удалены или заменены, когда 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 голосов
/ 02 августа 2010

VARCHAR должно быть достаточно. По моему мнению, данные VARCHAR будут проще использовать и работать с двоичными данными.

Встроенные поставщики членства ASP.NET также хранят хешированные пароли в виде полей VARCHAR.

1 голос
/ 02 августа 2010

большинство библиотек md5 / sha1 возвращают хеши, закодированные в base64, в этом случае varchar будет достаточно

...