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

Программным системам становится все труднее надежно аутентифицировать своих пользователей, правильно и безопасно обрабатывать конфиденциальные пароли. Один из наиболее распространенных подходов:

Хеширование паролей:

Сохранение хешированной версии пароля с использованием таких алгоритмов, как Argon2, bcrypt и т. Д., И использование его для аутентификации пользователей. К настоящему времени это минимальный базовый уровень для обработки конфиденциальных секретов, таких как пароль, все, что ниже этого (например, в виде обычного текста или закодированного), означает, что вы, вероятно, делаете плохой поступок, остановите его, вернитесь в безопасность !.

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

  • Требовался доверенный сервер для безопасной обработки и хранения хешированных паролей (который обещает не регистрировать пароли 😀)
  • Злоумышленник с большим словарем паролей и взломанной базой данных может определить пароль пользователя.
  • Злоумышленник может перехватить (атака MITM) связь между клиентом и сервером и получить пароль.

В данном случае нам нужна была надежная система доказательства с нулевым разглашением (без передачи пароля), которая выполняет взаимную аутентификацию на клиенте и сервере. Давайте посмотрим на застенчивую и менее популярную реализацию под названием S ecure R emote P assword (SRP).

Безопасный пароль удаленного доступа (SRP)

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

Это протокол с нулевым разглашением, в котором серверу не нужно хранить информацию, эквивалентную паролю (хешированная версия), и клиенты могут безопасно аутентифицироваться на сервере. А перехватчик или злоумышленник не может получить какую-либо значимую информацию для выполнения атаки. SRP предлагает большие преимущества, такие как,

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

Как это работает?

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

Регистрация:

Это первый шаг в процессе, на котором клиент передает определенную информацию для будущей аутентификации. поэтому во время регистрации клиент,

  • генерирует случайную соль
  • клиент передает имя пользователя, пароль и соль математической функции (KDF) для получения x
  • затем он генерирует нечто, называемое верификатором, используя производные x и группу SRP (подробнее об этом позже ).
  • Затем он отправляет на сервер верификатор, соль и группу SRP вместе с именем пользователя, и сервер сохранит верификатор и соль для пользователя.
Client(username, verifier, salt) → Server stores (verifier, salt) for user 

Давайте посмотрим на используемые термины,

Salt - случайная строка, используемая при вычислении верификатора

KDF - функция получения ключа, которая преобразует пароль в очень большое число, например: PBKDF и т. Д.

Группа SRP - состоит из одного большого простого числа и генератора. вы можете выбрать одну из нескольких групп, например: 1024 бит, 2048 бит и т. д.

Проверяющий - это случайная строка, сгенерированная из x, а не хешированная версия пароля, также ее нельзя эффективно использовать для угадай пароль.

Теперь, когда регистрация завершена, пользователь готов к аутентификации на сервере.

Аутентификация:

Это интересная и запутанная часть, чтобы доказать, что пользователь знает свой пароль, клиент и сервер обмениваются неконфиденциальной информацией, чтобы независимо генерировать ключ и использовать его для проверки.

На стороне клиента:

  • Клиенты отправляют запрос на сервер, чтобы получить соль и группу SRP для данного имени пользователя.
  • затем он передает имя пользователя, пароль, соль в KDF для получения x (так же, как и во время регистрация)
  • он также генерирует одноразовое эфемерное значение a (частное), а его аналог A (общедоступный) с использованием группы SRP были частными a хранится в памяти, а его общедоступное значение A отправляется на сервер.

На стороне сервера:

Сервер при отправке соли обратно пользователю,

  • генерирует одноразовое эфемерное значение b (частное), его аналог B (общедоступное) с использованием группы SRP, сохраняет частное значение b во временном хранилище и отправляет общедоступное значение B клиенту .
Client(username) → Server returns (salt, SRP group, B)

Что только что произошло 🤯?

Звучит запутанно, не правда ли? (x, a, b, A, B, KDF, verifier)! Честно говоря, мне тоже потребовалось время, чтобы понять. Проще говоря,

  • Пароль не был передан на сервер
  • Вместо этого клиент и сервер обмениваются A и B
  • Таким образом, клиент с (x, a, B) и сервер с (verifier, b, A), использующие разные вычисления, могут получить одно и то же значение, которое используется как ключ шифрования сеанса (доверять математике)

Проверка:

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

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

Таким образом, клиент и сервер успешно подтвердили, что они знают пароль пользователя и законны, и теперь могут использовать ключ шифрования сеанса в качестве ключа симметричного шифрования для обмена зашифрованными сообщениями. Круто 😎

Демо SRP

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

Для этой демонстрации мы будем использовать реализацию javascript thinbus-srp-npm, так как с ней идет демонстрационный пример проекта. Вот ссылка на демонстрационный проект,



Просто клонируйте указанный выше проект и установите зависимости, запустив,

npm install

Примечание: на вашем компьютере должны быть установлены узел и NPM.

Затем запустите приложение локально,

npm start

вы должны увидеть сообщение о запуске сервера,

> node server.js
Node has started on port 8080

перейдите по адресу http: // localhost: 8080 в своем браузере,

Регистрация:

Перед аутентификацией нам необходимо зарегистрировать пользователя, перейти по ссылке Register using SRP на главной странице,

Введите имя пользователя и пароль по вашему выбору и нажмите «Отправить». Посмотрим сетевой запрос на регистрацию,

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

Аутентификация:

Перейдите на главную страницу и нажмите Login using SRP,

Введите то же имя пользователя и пароль и нажмите «Войти». Давайте посмотрим на этот сетевой запрос,

Первый шаг - получить соль и вызов сервера B для данного имени пользователя, поэтому первый запрос вызовет /challenge конечную точку, которая выглядит следующим образом:

Сервер возвращает соль, а также генерирует одноразовую эфемерную пару (b, B) и возвращает общедоступное значение B в ответе.

Затем клиент вычисляет необходимое значение и выполняет вызов /authenticate,

Как видите, клиент отправляет следующую информацию:

A - одноразовое эфемерное общедоступное значение клиента
имя пользователя - имя пользователя
M1 - это зашифрованное сообщение с использованием сгенерированный сеансовый ключ для проверки сервером

Таким образом, сервер расшифровывает сообщение M1 и проверяет его, в случае успеха, затем генерирует M2 (зашифрованное сообщение с использованием своего сеансового ключа) и возвращается клиенту для проверки. Так что здесь проверка взаимна. Наконец-то вы поняли,

Примечание. В этом сообщении не передаются ни пароль, ни ключ сеанса.

Заключение

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

Ссылка

- - Если вас интересуют похожие истории, посмотрите - -