Хеширование пароля с перцем и солью в C# с использованием Rfc2898DeriveBytes

Я хотел бы хешировать пароли, используя PBKDF2 с перцем и солью в С#. Я немного новичок в криптографии, поэтому не стесняйтесь поправлять меня, если я ошибаюсь.

Я использую класс Rfc2898DeriveBytes, потому что (по словам других пользователей Stackoverflow) bcrypt и другие алгоритмы хеширования изначально не поддерживаются и не проверяются в C#, поэтому это может представлять угрозу безопасности. Цель этого поста не в том, чтобы начать дискуссию о том, какой алгоритм хеширования является лучшим. > Bcrypt в C# Stackoverflow

Моя цель: каждый пароль получит случайную соль и перец, пароль будет хеширован с определенным количеством итераций.

Мой вопрос: Плохо ли иметь больший размер ввода по сравнению с желаемым размером хэша, и правильно ли моя реализация?

  • Пример: (PasswordInput (?) + Pepper (16 байт) + Salt (16 байт) > HashOutput (20 байт)

Мой код

public class GenerateHash
{
    //Fields
    private const int saltSize = 16;
    private const int hashSize = 16;
    private const int iterations = 10000;
    private const string secretPepper = "Secret 16 Byte pepper."; 

   //Properties
    private string inputId { get; set; }

    //Methods
    public byte[] GeneratePBKDF2String(string inputId, string secretPepper, int saltSize, int 
    hashSize, int iterations)
    {
        // Generate a random salt.
        RNGCryptoServiceProvider cryptographicServiceProvider = new RNGCryptoServiceProvider();
        byte[] salt = new byte[saltSize];
        provider.GetBytes(salt);

        // Generate a salted hash with pepper.
        Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(inputId + secretPepper, salt, iterations);
        return pbkdf2.GetBytes(hashSize);
    }
}

Я понимаю это:

  • Хэш необратим.
  • Соль и перец добавляются для повышения безопасности и предотвращения атак радужного стола.
  • Соль — это уникальная и случайная строка, она не обязательно должна быть секретной и может храниться вместе с хешем в базе данных.
  • Перец не уникален и используется для каждого хэша. Это секрет, и он не хранится в базе данных.
  • Для соли и перца следует использовать не менее 128 бит (16 байт > 16 символов).
  • Для алгоритма должно быть использовано не менее 10 000 итераций.

Исследование: Microsoft Rfc2898DeriveBytes, Пример кода


person Coding-Is-An-Adventure    schedule 13.12.2019    source источник


Ответы (2)


PBKDF2 (с SHA-1), который реализует ужасно названный Rfc2898DeriveBytes, использует повторяющийся HMAC с паролем, закодированным в байтах, в качестве ключа. Как правило, HMAC просто выполняет метод заполнения для клавиши ввода (ipad и opad, если вы хотите найти ее). Это заполнение соответствует размеру входного блока хеш-функции. Однако давайте посмотрим на определение HMAC в HMAC RFC:

Обозначим через B длину таких блоков в байтах (B=64 для всех приведенных выше примеров хеш-функций), а через L длину выходных хэшей в байтах (L=16 для MD5, L=20 для SHA-1). ). Ключ аутентификации K может иметь любую длину вплоть до длины блока хэш-функции B. Приложения, использующие ключи длиннее B байтов, сначала хэшируют ключ, используя H, а затем используют результирующую строку L байтов в качестве фактического ключа для HMAC.

В вашем случае, если ваш закодированный пароль длиннее 64 - 16 = 48 байт (где 16 - размер перца), ваш HMAC может работать медленнее. Однако интеллектуальная функция PBKDF2 может обнаружить это и обойти проблему, выполнив начальную часть хеширования только один раз.

Таким образом, если ваш пароль превышает 48 байт, вы можете дать некоторую выгоду злоумышленнику, если:

  1. ваша реализация не настолько умна и
  2. реализация злоумышленника умна.

Обратите внимание, что размер выходного хэша не имеет к этому никакого отношения. Вы можете использовать PBKDF2 с SHA-512 — с размером блока 1024 бита, а не 512 бит для SHA-1 и SHA-256 — в случае, если это проблема.

Выходной размер хеш-функции хеш-функции в PBKDF2 (по умолчанию SHA-1) имеет значение, если вы запрашиваете больше, чем размер вывода в байтах. В этом случае вы также возвращаете преимущество злоумышленнику. К счастью, вы запрашиваете только 16 байтов в hashSize (имя переменной, которое вы можете изменить на passwordHashSize, чтобы избежать путаницы).


Я это понимаю:

О, Боже ;)

  • Хэш необратим.

Криптографическая хеш-функция и хеш-функция пароля необратимы, другие хеш-функции могут быть обратимыми.

  • Соль и перец добавляются для повышения безопасности и предотвращения атак радужного стола.

Для этого вам понадобится только соль. Перец полностью предотвращает угадывание пароля злоумышленником, если его можно сохранить в безопасности и если он достаточно надежен.

  • Соль — это уникальная и случайная строка, она не обязательно должна быть секретной и может храниться вместе с хешем в базе данных.

Это правильно.

  • Перец не уникален и используется для каждого хэша. Это секрет, и он не хранится в базе данных.

Или он сам зашифрован и хранится в базе данных, но да, в конце концов его нужно так или иначе обезопасить.

  • Для соли и перца следует использовать не менее 128 бит (16 байт > 16 символов).

Ну это как бы верхний предел, я бы сказал от 64 до 128 полностью случайных бит, желательно больше 80. Однако не каждый символ можно сопоставить с байтом, так что ваш перец вряд ли будет полностью случайным - плохая идея для чего-то, что в основном является секретным ключом.

Обратите внимание, что параметр конфигурации соли PBKDF2 может иметь любой размер до 64–8–4 = 52 байта, прежде чем для SHA-1 потребуется шифрование другого блока. По этой причине соль и перец обычно объединяются. Это также позволит вам использовать настоящий случайный перец. Таким образом, в пароле остается больше символов (64).

  • Для алгоритма должно быть использовано не менее 10 000 итераций.

Обычно мы рекомендуем около миллиона в настоящее время. Но на самом деле любое количество циклов процессора, которое вы можете выделить, усложняет задачу противнику. Вопрос немного спорный, если противник действительно не может добраться до перца, конечно. В этом случае достаточно одного раунда, но вы можете использовать большее количество итераций в качестве второй линии защиты (например, от системных администраторов, пытающихся получить пароли ваших пользователей, используя копию базы данных).

person Maarten Bodewes    schedule 14.12.2019

  1. Наличие ввода больше, чем размер вывода, не является проблемой. Хорошая хэш-функция должна противостоять всем атакам, даже если входные данные действительно велики.
  2. Говоря о хороших хеш-функциях: размер вывода в 20 байт намекает на использование SHA-1. SHA-1 настолько сломан, что практические коллизии уже существуют, поэтому его не следует использовать. (Я не знаю, является ли Rfc2898 безопасной схемой, если коллизии для SHA-1 существуют или нет, но когда дело доходит до безопасности, лучше перестраховаться, чем сожалеть.
  3. В остальном реализация выглядит нормально. Я не в курсе C #, но вы, кажется, используете криптографический ГСЧ для соли.
  4. Вы перец также должны быть случайными.
  5. 128-битные (16-байтовые) ключи вполне подходят, если ваши пароли не нужно хранить в безопасности более 50 лет или около того.
person VincBreaker    schedule 13.12.2019
comment
Rfc2898 использует HMAC-SHA1, и я не знаю, делает ли это реализацию более безопасной. Rfc2898 можно настроить так, чтобы он имел больше итераций, но его слабость заключается в том, что его можно легко взломать с помощью специализированного оборудования с небольшим объемом оперативной памяти. В конечном итоге это будет более дорогостоящим для защитника по сравнению с злоумышленником. Scrypt решает эту проблему, потому что требует больше оперативной памяти. Argon2 также был построен на этом принципе, но, к сожалению, он не проверен Microsoft на C# (насколько мне известно). Я хотел бы услышать об альтернативах, если они проверены на C#. - person Coding-Is-An-Adventure; 14.12.2019
comment
HMAC-Construction позволяет использовать уже сломанные схемы (даже HMAC-md5 безопасен, насколько мне известно), но использование ненарушенного алгоритма, безусловно, лучше. Хотя я не знаю, проверено это или нет, похоже, существует привязка C# для официальной реализации Argon2 c github.com/alipha/csharp-argon2 - person VincBreaker; 14.12.2019