Откуда берутся значения хеш-соли?

12

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

Морган Херлокер
источник
@DevArt, я подумал, что это лучше подходит здесь, потому что это требует очень субъективного ответа. Солт-значение может быть получено откуда угодно, поэтому я спрашиваю: «Как вы думаете, где наиболее безопасное место для получения солт-значений: клиент или сервер?»
Морган Херлокер

Ответы:

7

У меня обычно есть столбец created TIMESTAMPв пользовательской таблице, чтобы я мог видеть, когда пользователь зарегистрировался. Мне не нравится добавлять дополнительный столбец для Salt, поэтому я использую столбец timestamp в качестве соли:

SHA1(password + created)
Jonas
источник
Затем я предполагаю, что когда пользователь снова входит в систему, вы извлекаете дату на основе имени пользователя, когда вы перепроверяете для проверки?
Морган Херлокер
1
@Prof: Да, точно так же, как и у вас, если у вас есть конкретный столбец для соли, так что нет никакой разницы с этой точки зрения.
Джонас
7

Это имеет значение?

Соль служит двум целям. Это делает нецелесообразным использование больших таблиц предварительно хешированных паролей («радужных таблиц»), а также делает идентичные пароли выглядеть по-разному в списке хэшей. Если идентичные пароли выглядят по-разному, это помогает избежать проблемы, когда несколько человек используют один конкретный пароль, который, вероятно, является распространенным слабым паролем.

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

Используйте любой удобный метод для получения соли. Если существует много потенциальных значений соли (ранние системы Unix часто использовали два байта для возможного числа 65536) по сравнению с количеством учетных записей, полуслучайное назначение почти никогда не выдаст дублирующую соль.

Дэвид Торнли
источник
1
Я обычно видел вторую проблему - идентичные пароли выглядят по-разному - решается путем объединения имени пользователя, соли и пароля и хеширования всей строки. Это устраняет необходимость генерировать уникальную соль для каждого аккаунта.
Джастин Кейв
1
@Justin: интересно, я никогда не видел, чтобы имя пользователя использовалось как часть хэша, но это действительно хороший способ добавить энтропию. Я все еще использовал бы псевдослучайную соль, хотя бы потому, что ее создание не стоит больших затрат.
Матье М.
2
@Matthieu Недостатком является необходимость хранить его где-то, и если обе стороны транзакции нуждаются в этом, необходимо также отправить его. С именем пользователя обе стороны уже знают это.
Мэтью Фредерик
2
@Justin: в этом случае вы используете имя пользователя в качестве соли. Это решает обе задачи: создание непрактичных радужных таблиц и создание похожих паролей по-разному.
Дэвид Торнли
@ Дэвид - Правда, вы можете смотреть на это как на то, что имя пользователя становится частью соли. Мне все еще нужна дополнительная соль, чтобы злоумышленник не мог использовать радужную таблицу для поиска комбинаций имени пользователя и пароля. Без явной соли вы просто увеличиваете размер строки, которая нужна злоумышленнику из радужной таблицы, на длину имени пользователя (которая может быть короткой и либо полностью строчной, либо полностью заглавной). Постоянной соли достаточно, чтобы предотвратить атаку по радужному столу, если ваш сайт не достаточно велик, чтобы злоумышленник сгенерировал специфичный для сайта радужный стол.
Джастин Кейв
3

Каждый раз, когда вы хотите сохранить новый пароль (регистрация, сброс пароля, обновление пароля), один хороший метод:

  • генерировать новую соль
    • использовать криптографически безопасный генератор псевдослучайных чисел
    • использовать соль приличного размера - хорошее значение - размер блока базового алгоритма хеширования (может быть SHA-256)
  • создать новый пароль токен
    • создать функцию hmac из основного алгоритма хеширования (может быть, SHA-256), используя соль в качестве ключа hmac
    • for i in (0...65536) { password = hmac(password) }
    • Результатом повторного применения функции hmac является токен пароля
  • хранить соль и токен пароля
    • не храните оригинальный пароль
    • При желании хранить основной алгоритм хеширования и растяжки для обнаружения
yfeldblum
источник
1

Используйте рамки. В .NET вы можете использовать RNGCryptoServoiceProvider ...

        // If salt is not specified, generate it on the fly.
        if (saltBytes == null)
        {
            // Define min and max salt sizes.
            int minSaltSize = 4;
            int maxSaltSize = 8;

            // Generate a random number for the size of the salt.
            Random  random = new Random();
            int saltSize = random.Next(minSaltSize, maxSaltSize);

            // Allocate a byte array, which will hold the salt.
            saltBytes = new byte[saltSize];

            // Initialize a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            // Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes); 
        }

Другие структуры должны иметь аналогичные классы, которые вы можете использовать. Для достижения случайности программное обеспечение часто использует пользователя по сравнению Randomс указанным выше. Случайное перемещение мыши в определенной области для получения соли - опция, используемая TrueCrypt. Это сводится к вашим конкретным потребностям и уровню безопасности; так как ваша соль может быть просто !@#$%.

Аарон Макивер
источник
1

Вы создаете соленый сервер и назначаете его учетной записи пользователя при его создании. Лучше использовать некоторый API-интерфейс для криптографии, доступный в вашей среде, но в принципе подойдет любая последовательность.

Обычно вещи хранятся так:

User
-------------------
ID
Username
PasswordHashWithSalt

Пример:

PasswordHashWithSalt =

A15CD9652D4F4A3FB61A2A422AEAFDF0DEA4E703 j5d58k4b56s8744q


источник
Назначить его на основании чего хотя? Разве это не должно происходить из некоторого значения, которое останется на месте, чтобы его можно было реплицировать при повторном входе пользователя после создания?
Морган Херлокер
Под «назначить» я имею в виду создание соли для каждой пары имя пользователя / пароль (учетная запись) и сохранение ее в базе данных. Когда вам нужно выполнить вход в систему, вы используете эту сохраненную соль, чтобы проверить вещи.
1

Используйте bcrypt и прочитайте эту статью, поскольку обычные хэши не являются серьезной защитой в наше время.

Рассмотрите возможность использования протокола паролей с нулевым знанием SDR, который имеет множество библиотек с открытым исходным кодом и не имеет патентов.

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

simbo1905
источник