«Пароль» - этот сумасшедший кусок веревки дорогого стоит, привлекает много внимания, но его очень сложно обработать и скрыть. Даже при многофакторном подходе крайне важно правильно спроектировать первый шаг (это то, что знает пользователь).
Программным системам становится все труднее надежно аутентифицировать своих пользователей, правильно и безопасно обрабатывать конфиденциальные пароли. Один из наиболее распространенных подходов:
Хеширование паролей:
Сохранение хешированной версии пароля с использованием таких алгоритмов, как 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 состоит из множества вычислений, двусторонней связи между клиентом и сервером и сложных терминов для понимания. К счастью, поскольку это открытый протокол, доступно несколько реализаций, облегчающих жизнь,
- Реализация Голанга (от 1Password)
- Реализация Javascript
- посетите Wiki, чтобы узнать больше
Для этой демонстрации мы будем использовать реализацию 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 в качестве надежной системы паролей, даже пароль с низкой энтропией, который можно использовать безопасно.
Ссылка
- Https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol
- Https://godoc.org/github.com/agilebits/srp
- Https://github.com/simbo1905/thinbus-srp-npm
- - Если вас интересуют похожие истории, посмотрите - -