Защита паролем

В настоящее время я использую определенную схему для защиты паролей, и я думаю, что мне есть что улучшить. Реализация на Java, поэтому я предпочитаю использовать SHA-2 512 в качестве формы шифрования.

В настоящее время у меня есть модель клиент-сервер, поэтому могут происходить следующие вещи:

  • Клиент хочет войти в систему, он отправляет свой пароль с однократным обычным шифрованием SHA-2 512 по сети.
  • Сервер имеет пароли, хранящиеся в базе данных, например, SHA-2_512 (SHA-2_512 (пароль) + соль), причем внутренний SHA-2_512 (пароль) является «зашифрованным» паролем, который он получает по сети.
  • Проверка пароля выполняется на стороне сервера, и с сервера ничего не может просочиться, единственной возможной уязвимостью было бы, если бы кто-то мог считать ОЗУ, я думаю.

У меня есть эти вопросы:

  • Злоумышленник обычно создает атаки столкновений, когда хочет взломать пароль. Однако насколько достаточно атак столкновений? Если пароль необходимо использовать для других приложений, таких как Outlook.com, Facebook или что-то еще (которые, вероятно, используют другую соль, поскольку они не имеют ничего общего с моими приложениями), как тогда достаточно атаки столкновений? Вам не нужен настоящий пароль?

  • Использует ли SHA-2 512 итерацию? И даже если это так, должен ли я изменить свои методы шифрования, чтобы автоматически использовать несколько итераций плюс предпочтительное количество итераций? Я также читал об использовании случайного числа итераций (в диапазоне), как детерменистически сохранить случайный фактор?

  • Должен ли я хранить системные секреты для каждой итерации в коде сервера? См. http://blog.mozilla.org/webappsec/2011/05/10/sha-512-w-per-user-salts-is-not-enough/ . Я мог бы хранить массив, который будет содержать статический секрет для каждой итерации, причем n-й секрет будет для n-й итерации. Никто не может знать секреты, они вычисляются один раз (я думаю, как шифрование какой-то случайной строки), а затем в основном сохраняются в ОЗУ сервера.

  • В настоящее время я отправляю введенный пароль от клиента на сервер как просто SHA-2_512 (пароль), следует ли улучшить этот процесс, и если да, то как? Я не могу использовать соли, потому что у клиента нет соли.

С Уважением.


person skiwi    schedule 19.05.2013    source источник


Ответы (1)


TLDR: вам необходимо отправить пароль по зашифрованному каналу, например TLS. Рассмотрите возможность использования bcrypt для хеширования паролей.

SHA-2 512 — это не алгоритм шифрования, это алгоритм дайджеста сообщения. Алгоритму шифрования требуется ключ и сообщение для шифрования. Он производит зашифрованный текст. Важно то, что алгоритм шифрования имеет алгоритм дешифрования.

ciphertext = E(key, plaintext);
plaintext = D(key, ciphertext);

Дайджест сообщения берет часть открытого текста и создает дайджест сообщения. Не существует соответствующего обратного механизма для получения дайджеста сообщения и извлечения исходного сообщения. Секретного ключа тоже нет.

digest = hash(plaintext);

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

digest1 = hash(guess1);
digest2 = hash(guess2);    //repeat with lots of guesses

Во-первых, отправка хэша по сети небезопасна. Его необходимо отправить через какой-либо безопасный механизм связи, такой как SSL. Если злоумышленник сможет перехватить хэш при обмене данными, он сможет подобрать исходный пароль.

коллизия хешей — это не то же самое, что перебор пароля. Конфликт хэшей возникает, когда два различных сообщения создают один и тот же дайджест сообщения.

digest1 = hash(plaintext1);
digest2 = hash(plaintext2);
if ( ( plaintext1 != plaintext2 ) && ( digest1 == digest2 ) )  
    // hash collision

SHA-512 не имеет итераций, предназначенных для предотвращения грубой силы. Набор алгоритмов SHA разработан, чтобы быть эффективным. Причина добавления итераций при хэшировании паролей заключается в увеличении времени, необходимого для перебора пароля. Идея заключается в том, что стоимость легитимной попытки входа в систему и выполнения 100 итераций ничтожно мала по сравнению с затратами злоумышленника, имеющего миллионы паролей, каждый из которых требует 100 итераций. Добавление дополнительных итераций помогает уменьшить влияние повышения скорости процессора (что поможет злоумышленнику быстрее выполнить большее количество итераций).

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

Отправка SHA-2 512 в виде открытого текста небезопасна. Вы должны отправить его по зашифрованному каналу, такому как SSL.

Сказав все это, SHA-2 не предназначен для использования в качестве алгоритма хеширования паролей. Он предназначен для проверки сообщений и должен быть эффективным. Рассмотрите возможность использования специально созданного алгоритма хеширования паролей. Одним из примеров является bcrypt. Он спроектирован так, чтобы быть сложным в вычислительном отношении, и имеет встроенную соль и итерации.

person Steve    schedule 19.05.2013
comment
Я немного исследовал, и я думаю, что это важное примечание, которое нужно добавить: BCrypt должен быть выполнен на стороне клиента для авторизации (и на стороне сервера один раз для регистрации / смены пароля). Так что нагрузка на сервер действительно очень низкая. Поправьте меня, если я ошибаюсь. Есть ли способ определить хороший фактор работы? - person skiwi; 19.05.2013
comment
@skiwi Я не думаю, что вам следует выполнять расчет bcrypt на стороне клиента. Не могли бы вы поделиться своими ссылками, пожалуйста? Нагрузка на сервер при использовании bcrypt по-прежнему довольно низкая, но нагрузка на злоумышленника, пытающегося взломать его путем попытки 1000 догадок, очень высока. - person Steve; 19.05.2013
comment
Взгляните на stackoverflow.com/questions/4443476/optimal-bcrypt- рабочий фактор для определения рабочего фактора. - person Steve; 19.05.2013
comment
Можно ли безопасно использовать BCrypt без добавления дополнительной соли (от меня) к паролю, который вы хотите хэшировать? Я знаю, что он уже содержит соль, этого достаточно для работы? Также Java дает char[] из JPasswordField, но BCrypt заставляет меня использовать String, что означает, что пароль плавает в памяти, это проблема? - person skiwi; 19.05.2013
comment
Да, для работы достаточно. Вам не нужно добавлять туда еще один. - person Steve; 19.05.2013
comment
Это немного беспокоит см. здесь. Однако, если злоумышленник уже находится на клиентской машине и читает память процесса, у него есть другие способы получить пароль (например, регистрация ключей). Я не позволю этому помешать тебе пользоваться библиотекой. - person Steve; 19.05.2013
comment
Не могли бы вы заглянуть в мой новый пост? stackoverflow.com/questions/16636711 / К сожалению, я не нашел возможность написать личное сообщение на этом сайте, так как это не лучшая идея. - person skiwi; 19.05.2013