Пароль хэширует разные соли с тем же именем пользователя

Мы ввели шифрование пароля на нашем сайте. Соль рассчитывается, как показано ниже:

Rfc2898DeriveBytes hasher = new Rfc2898DeriveBytes(Username.ToLowerInvariant(),
           System.Text.Encoding.Default.GetBytes("Wn.,G38uI{~6y8G-FA4);UD~7u75%6"), 10000);
string salt = Convert.ToBase64String(hasher.GetBytes(25));

Для большинства имен пользователей соль всегда одинакова. Но для некоторых имен пользователей он меняется при каждом вызове. Может кто-нибудь сказать мне, что мы делаем не так?

1 ответ

Решение

Предполагая, что вы используете RFC2898DeriveBytes для хеширования и самого пароля, тогда @CodesInChaos правильно, то, что вы делаете неправильно:

  • Создание соли на основе имени пользователя вместо использования криптографического PRNG для создания новой соли для каждого пользователя.

byte[] salt1 = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
  {
  // Fill the array with a random value.
  rngCsp.GetBytes(salt1);
  }

  • Затем соль должна храниться в незашифрованном виде в вашей базе данных вместе с хэшем пароля и счетчиком итераций (чтобы вы могли изменить его), а также, вероятно, и с кодом версии (чтобы вы могли изменить его снова, т. Е. Текущий метод вычисления соли - это версия 1). и случайная соль - версия 2).

    • Тратить 20000 итераций PBKDF2 на соль, вместо того, чтобы тратить ее на фактический хэш пароля!
  • 10000 итераций для первых 20 байтов, поскольку RFC2898DeriveBytes - это PBKDF2-HMAC-SHA-1, а SHA-1 имеет собственный 20-байтовый выход
  • Еще 10000 итераций для следующих 20 байтов, которые затем усекаются только до 5, необходимых для получения 25-байтового вывода.
  • Это слабость, поскольку защитник должен тратить время на соль при каждом входе в систему, независимо от того, тратится ли он на соль или хеширование пароля. Злоумышленник должен потратить это время один раз для каждого имени пользователя, а затем он собирается сохранить результаты и попробовать _ миллионы (где _ очень много) предположений пароля.
    • Таким образом, у атакующего маргинальное преимущество больше, чем у обычного, потому что он может предварительно рассчитать соль, в то время как вы должны рассчитать ее на лету.

Если вы не используете RFC2898DeriveBytes, другую реализацию PBKDF2, BCrypt или SCrypt для фактического хеширования пароля, то это то, что вы делаете неправильно.

Некоторое сокращение имени пользователя, но не все время, полностью случайное; просто убедитесь, что не урезали пароли до того, как они хешируются

Другие вопросы по тегам