Как безопасно хранить хэширование пароля в памяти при создании учетных записей?

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

Чтобы быть более конкретным, как обеспечить, чтобы строка, содержащая пароль, была собрана мусором в течение достаточно короткого промежутка времени?

Ответ 1

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

Arrays.fill(password, ' ');
password = null;

Я только заметил, что обнуление пароля будет немного параноидальным, но вы можете сделать, если это успокоит вас:)

Ответ 2

Вы не используете String. Вы используете char [], а затем перезаписываете char [] по завершении.

Нет никаких гарантий, когда дело доходит до сбора мусора (кроме того, что финализатор будет работать до того, как объект будет собран). GC может никогда не запускаться, если он запускается, он никогда не может GC String, в котором есть пароль.

Ответ 3

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

Ответ 4

Два слова: Локальная область. Объявленные переменные для обработки паролей должны обладать абсолютной минимальной областью.

Как только переменные выходят из области видимости, объекты имеют право на сбор мусора.

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

Ответ 5

Невозможно гарантировать, что прозрачные текстовые пароли удаляются из памяти на Java.

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

Лучший подход заключается в том, чтобы клиент шифровал пароль, как предлагает @Mork0075. Однако, хотя это означает, что вы не можете легко получить пароль, программа все равно может получить зашифрованную версию паролей и поэтому притворяется пользователем. Кстати, это шифрование всего соединения с помощью SSL.

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

Ответ 6

Используйте вызов пароля:

  • Сервер выбирает значение и отправляет его клиенту
  • Сервер выполняет односторонний перевод с паролем и вызовом, например. MD5(CONCAT(challenge, password)) и назначает его сеансу.
  • Пароль с обычным текстом теперь выходит за рамки и готов к сбору мусора.
  • Клиент также выполняет тот же перевод и отправляет результат на Сервер.
  • Если сервер и клиент выбирают одно и то же окончательное значение, клиент аутентифицируется.

Этот метод предотвращает повторные атаки, но требует, чтобы значение было очень непредсказуемым (случайным) и не часто использовалось повторно (long).

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