Признайся, разработчик, ты же любишь отправлять пароль в теле POST‑запроса из формы входа открытым текстом, ведь «там же TLS, всё зашифровано»? Судя по тому что я вижу в интернете, эту традицию соблюдают многие, и ИИ — не исключение. Одни продолжают запрашивать по сети пароли, прикрытые звёздочками, другие — используют одинаковый пароль в десятке различных сервисов. Даже Госуслуги не стали исключением. Открытый пароль гуляет неизвестно где, но все спокойны. «Задача неприоритетна» уже много лет.

Что не так?
В подавляющем большинстве продакшн‑инфраструктур TLS терминируется на балансировщике, reverse‑proxy (nginx, Envoy, HAProxy) или на CDN/edge‑узле (Cloudflare, Fastly, Yandex Cloud). Дальше, внутри периметра — до контейнера с приложением, до соседнего микросервиса, до очереди сообщений — трафик идёт по обычным HTTP, gRPC и так далее, потому что «мы же внутри, тут все свои». Пароль в этот момент — обычная строка в теле запроса, читаемая любым, кто оказался на этом внутреннем участке пути. Утечка может произойти через банальный log.info(req.body), забытый в middleware, или через APM/error‑tracking системы типа Sentry, которые могут сохранить полное тело HTTP‑запроса при ошибке, а аутентификация рано или поздно отпятисотит.
Это происходило с крупными компаниями:
В 2018 году GitHub обнаружил у себя баг, из‑за которого пароли пользователей в открытом виде записывались во внутренние логи компании, и эти незашифрованные пароли были доступны небольшому числу сотрудников GitHub. При этом в обычном режиме пароли надёжно хранились через bcrypt — проблему создал именно баг, из‑за которого plaintext‑версия попадала в лог.
Практически одновременно похожая история случилась у Twitter: компания сообщила о баге, из‑за которого пароли пользователей сохранялись во внутреннем логе в незамаскированном виде. По словам техдиректора компании, из‑за ошибки пароли записывались в лог до того, как полностью проходили процесс хеширования, хотя в норме система использовала bcrypt для маскирования паролей.
В обоих случаях TLS работал штатно. Проблема была в том, что где‑то на пути между приёмом запроса и вызовом функции хеширования пароль на короткое время существовал в виде обычной строки, и эта строка попала не туда.
Пароль — это тайна
Ты наверное с оголтелым снобизмом заявишь что пароли от разных сервисов должны быть разные, сложные, храниться в менеджере паролей, и так далее. Но в реальном мире это не работает. Клиент всегда будет пытаться задать пароль «111». (часто просто потому, что ему вообще не нужна была регистрация). И только ограничения разработчика заставляют его уйти придумать правильный пароль. Можно ограничить количество символов и их разнообразие, но вот чего разработчик никогда не сможет — это заставить придумать уникальный пароль. Значит мы живём в мире где один пароль пользователя подходит к разным сервисам. Это факт. А коль скоро это факт, утечка его пароля из твоей системы вызывает последствия неопределённых масштабов, выходящие далеко за пределы тех рисков и ответственности, на которые ты мог рассчитывать.
Если тебе плевать на судьбу своих пользователей, предлагаю рассмотреть немного абсурдный, но занимательный пример.
Сами по себе логин и пароль не являются персональными данными, но ровно до тех пор, пока я не запишу туда свои паспортные данные и отправлю на сервер. Ну а что? Такой вот у меня пароль. Так уж вышло, что по нему можно однозначно идентифицировать мою личность. Как только сервер принял паспортные данные в виде пароля и пытается их захешировать, у владельца сервера тут же возникает статус оператора персональных данных со всеми вытекающими. Чувствуешь градус абсурда?
Можно ещё повысить этот градус, если передать в качестве пароля запрещённую информацию. Представь, твой сервер ночами напролёт хеширует цопэ, которое ему присылают в качестве пароля, а особо понравившееся nginx сохраняет в access‑log, а Sentry ещё и «распространяет».
Здорово, правда?
Я это к чему — сам пароль серверу для аутентификации вовсе и не нужен, и знать его — лишняя головная боль. Пароль — это «чужое». Нельзя трогать. Ай‑яй‑яй. Надеюсь, что мне удалось донести эту простую мысль.
Что делать
Главное правило — Пароль не должен покидать клиента.
Хеширование пароля на клиенте
Самый ленивый способ. Клиент отправляет hash(password + salt). Исходный пароль не светится больше нигде и никогда, но сам хеш становится эквивалентом пароля, который при утечке больше нигде кроме данного сервера использовать не получится. Необходимо применять современные алгоритмы хеширования, например Argon2, который сокращает скорость перебора до нескольких паролей в секунду. В соль нужно включить домен сервиса или уникальный идентификатор: иначе два сайта, внедрившие одинаковую схему с одинаковой солью, выдадут одинаковые хеши, и перехват на одном откроет вход на другой. Удобный вариант — соль из домена и логина, вычисляемая на клиенте:
сient_hash = Argon2id(password, salt = domain || login)
Сервер всё так же обязан хранить свой хеш от присланной строки, а не её саму, иначе кража базы даст эквиваленты паролей всех пользователей.
Для большинства пет‑проектов этого уже вполне достаточно. Это далеко не лучшее решение, но определённо лучше открытого пароля тем что закрывает главную проблему, связанную с утечками - компрометацию оригиналов паролей пользователей.
Challenge‑Response Authentication
Недостаток предыдущего метода в том, что хеш на клиенте становится эквивалентом пароля. Если злоумышленник получит этот хеш, он сможет аутентифицироваться на текущем сервере сколько угодно (replay‑атака). Этот риск был и раньше, мы его не добавили. Чтобы снизить этот риск можно реализовать трёхшаговый обмен:
Challenge. Клиент запрашивает у сервера одноразовый nonce (случайные байты). Сервер его генерирует, отдаёт и запоминает что отдал: логин пользователя, nonce, время, флаг использования — {login, nonce, timestamp, used}. Этот challenge имеет срок годности, например 1 минуту, после чего удаляется.
Response. Клиент вычисляет хеши:
сient_hash = Argon2id(password, salt = domain || login)proof_hash = Argon2id(client_hash, salt = nonce || timestamp)
и отправляет на сервер {login, timestamp, nonce, proof}. Argon2 на втором шаге можно запустить с лёгкими параметрами — данных немного, но одну итерацию прогнать стоит.Authentication. Сервер проверяет: nonce существует и не used; |now − timestamp| ≤ window; повторно хеширует хранимый client_hash с nonce || timestamp и сравнивает с proof:
expected = Argon2id(stored_client_hash, salt = stored_nonce || stored_timestamp)success = expected == proof
Чтобы исключить timing‑атаку, помечать nonce как used нужно при любом исходе проверки. а вместо посимвольного сравнения, как в псевдокоде выше, использовать функцию сравнения за постоянное время. Вычислять expected заранее на первом шаге ни в коем случае нельзя.
Как можно было заметить, сервер в этом случае вынужден хранить клиентский хеш пароля как есть, без хеширования на своей стороне. Учитывая что пароль уже захеширован на клиенте - это небольшая плата за закрытие ещё одной крупной уязвимости. Перехваченный proof бесполезен: nonce одноразовый, а timestamp делает его недолговечным, так что украденный из логов прокси или перехваченный по сети пакет годен максимум минуту.
Так шаг за шагом, можно изобретать идеальный велосипед. Но, как это обычно бывает, всё уже придумали до нас, и можно сократить путь, взяв уже готовый заводской байк последней модели из коробки.
Сначала немного теории, потом будет пара конкретных современных алгоритмов.
ZKPP
Zero‑knowledge password proof (доказательство пароля с нулевым разглашением, ZKPP). Общее название механизма, который позволяет одной стороне (доказывающей) доказать другой стороне (проверяющей), знание пароля, не раскрывая его.
Это идея обычного доказательства с нулевым разглашением (ZK), адаптированная под низкоэнтропийный секрет. В отличие от длинного ключа, пароль имеет относительно мало символов, и его можно перебрать, поэтому протокол должен быть устроен так, чтобы перехваченный обмен не позволял перебирать пароли по словарю оффлайн: каждая догадка должна требовать отдельного обращения к тому, кто может его проверить. Полностью перебор не исключить: теоретически можно стучаться на сервер и подбирать пароль бесконечно долго. Rate limit и другие технические ухищрения это ограничивают, но не исключают.
Но сам ZKPP отвечает только на вопрос «знает ли собеседник пароль». Аутентификация без выработки общего ключа почти бесполезна: она не привязана к конкретному обмену, поэтому её можно воспроизвести или перехватить с помощью man‑in‑the‑middle. Значит, нужен следующий шаг — превратить доказательство в ключ.
PAKE
Password‑Authenticated Key Exchange (PAKE) — общее название класса криптографических протоколов, в которых стороны на основе пароля вырабатывают общий высокоэнтропийный сессионный ключ. Не любой PAKE формально является ZKPP. Делятся на два типа:
Balanced PAKE — обе стороны знают один и тот же пароль (или одну и ту же его производную). В строгом смысле это не ZKPP, хотя применение у таких протоколов огромно: например, WPA3-SAE в твоём роутере. Но это не наш случай.
Augmented PAKE (aPAKE) — более подходящий для клиент‑серверных сценариев, в которых сервер хранит верификатор — уникальное производное, из которого нельзя легко восстановить пароль и которое нельзя переотправить для входа.
Любой приличный aPAKE даёт:
взаимную аутентификацию
установление сессионного ключа
защиту от офлайн‑перебора по перехваченному обмену (онлайн‑перебор остаётся и ограничивается только rate limit'ами).
Получаемый сессионный ключ нужен прежде всего самому протоколу: через него стороны подтверждают, что обмен прошёл с одним и тем же паролем именно в этой сессии, поэтому записанный обмен нельзя воспроизвести. Дальше уже сессия выдаётся как обычно (cookie с идентификатором, JWT или что ты там любишь). От кражи этой сессии PAKE не защищает. Его задача вполне конкретна: пароль и его эквивалент никогда не попадают на сервер, утечка базы не позволяет зайти, а перехваченный обмен не позволяет перебирать пароли офлайн. То что нам и было нужно.
Ниже пара современных представителей aPAKE на выбор — попроще и посложнее. Промежуточные популярные, но устаревшие протоколы я пропустил, ибо тысячи их.
SPAKE2+
RFC 9383, сентябрь 2023. Один из самых простых и актуальных aPAKE. Не путай со SPAKE2.
Каждый генерирует своё случайное число и отправляет собеседнику точку на эллиптической кривой, в которую замешано это случайное число и производное от пароля. Получив сообщение другой стороны, каждый комбинирует его со своим случайным числом и производным от пароля — и обе стороны приходят к одному и тому же общему секрету.
Модель угроз:
Перехват трафика — бесполезен. Атакующий получает одну онлайн‑попытку за сессию.
Утечка верификатора из базы — даёт офлайн‑перебор. Верификатор математически связан с паролем, поэтому кандидата можно проверить без участия сервера.*
Компрометация сервера в момент регистрации — тоже даёт офлайн‑перебор: сервер получает верификатор.*
Единственный тормоз для такого перебора — стоимость вычисления производного от пароля: Argon2 с нормальными параметрами и уникальная соль для каждого пользователя. Для длинного пароля этого достаточно.
OPAQUE
Золотой стандарт. RFC 9807 от 2025 г. Рекомендован IETF CFRG. Имеет строгое криптографическое доказательство безопасности.
Клиент отправляет «ослеплённое» значение (математическая маскировка пароля случайным множителем), сервер применяет к нему свою секретную функцию и возвращает результат, не видя, что именно обработал. Секрет этой функции — OPRF‑ключ: случайный скаляр, который сервер хранит вне базы (HSM/KMS/Vault), и без которого украденные верификаторы бесполезны для перебора. Сервер участвует в вычислении производного от пароля, не получая никакой информации о пароле, даже если Sentry в порыве энтузиазма запишет весь request body со стеком. Сверху OPAQUE добавляет обмен ключами на основе тройного Диффи‑Хеллмана: клиент и сервер взаимно проверяют, что общаются друг с другом, и договариваются об общем сессионном ключе.
Модель угроз:
Перехват трафика — бесполезен.
Утечка базы верификаторов — не даёт офлайн‑перебора: в базе нет серверного секрета, а без него прогнать кандидата через OPRF нельзя.
Компрометация сервера в момент регистрации: пароль не раскрывается, сервер видит только ослеплённые значения.
Полная компрометация сервера (ключ + база): офлайн‑перебор возможен, но по одному пользователю за раз и без заранее посчитанных таблиц. Под угрозой только совсем слабые пароли.
Компрометация TLS‑сертификата сервера (привет ТСПУ+НУЦ): вход и пароль это не раскрывает, взаимная аутентификация делает MITM бесполезным. Остальной трафик — уже не в его компетенции.
Минусы этого добряка в основном связаны с серверным ключом:
Серверный секрет придётся беречь. Он должен жить в HSM/KMS/Vault, а не в базе и не в репозитории.
при деплое ключ нужно безопасно доставить в приложение (через менеджер секретов, а не «как‑нибудь через env»);
при масштабировании на несколько серверов ключ должен быть одинаковым у всех;
при ротации нужно перерегистрировать всех пользователей или поддерживать сложную схему с двумя ключами одновременно;
при компрометации ключ приходится отзывать, перерегистрировать всех пользователей и принудительно менять пароли.
Стоимость. OPRF добавляет несколько операций на эллиптической кривой, а основная нагрузка обычно приходится на Argon2 на стороне клиента. Но на очень нагруженном сервисе лишние операции на каждый вход всё же заметны.
Аутентификация без пароля
Всякие Passkeys / WebAuthn — это отдельный дивный мир. Рассматривать его в рамках этой статьи не вижу смысла.
Ещё раз
Оставить это на потом — очень плохая идея, потому что переделывать аутентификацию на существующей базе будет больнее и для тебя, и для клиентов, особенно если проект взлетит и каждый чих начнёт измеряться деньгами.
Ничего придумывать не нужно. Всё стандартизировано, существуют библиотеки. Если не хочешь вникать в «эти ваши непонятные протоколы», делай хотя бы хеширование на фронте. Это всё равно будет сильно лучше чем отправлять голый пароль.
Да и в конце концов, не руками же тебе код писать.
Спасибо за внимание к этому вопросу. Распространите среди жильцов вашего ЖЭКа.
Комментарии (35)

Mr_Makadamia
06.11.2026 02:34Такой странный флёр от статьи появляется после прочтения. Буд-то мы в курилке собрались, и внезапно кто-то или некто решил поделиться своими мыслями, стараясь передать опыт ловли леща, без удочки, снастей, и вообще не выходя из дома!)) Даже, на пальцах не показал что и куда, и "...как это самое...". Но, потом, я понял, что человек учится вещать - это похвально, но печально что именно в этой ветке.//просто мысли в слух

mmMike
06.11.2026 02:34Самый ленивый способ. Клиент отправляет hash(password + salt).
делай хотя бы хеширование на фронте. Это всё равно будет сильно лучше чем отправлять голый пароль.
Простой, ленивый но ооочень не безопасный в том виде как описан. От мамкиных кулхакеров может и спасет (хотя… сколько на моей памяти было случаев, когда примитивные меры, начиная от XOR данных по простому алгоритму спасали от крупных проблем, потому что кулхакер не смог)
Утечка hash(password + salt) из трафика клиент->хост фактически эквивалента утечке пароля. Ну чуть больше сложностей при использовании украденного (например, модифицировать JS страницы в сборке браузера, который это позволит) и пароль в открытом виде особо и не нужен. Да и просто повторить запросы руками.
Более менее простая модификация такого способа дает хоть какую то защиту: Так же на хосте хранить пару hash(password || password_salt) + password_salt, что бы исключить одинаковые записи для одинаковых паролей. Или просто hash(password || username))
Рассчитывая что из БД то не утекут - оптимистично. Но иначе только + HSM. Говорить, что можно без HSM “у нас все зашифровано, мы сильную криптографию используем” - это как рядом с банковской сейфовой дверью под ковриком держать ключ/пароль от замка к этой двери.
ну а от клиента передавать не просто то, что находится на сервере для прямого сравнения, а например
Если нет понятия прикладной сессии, то можно от клиента отправлять hash(hash(password || username) || client_salt) + client_salt client_salt может включать текущее время для того, что бы сервер его извлек и контролировал время действия. Не панацея, но какая то защита от перехвата трафика и нелегитимного использования на постоянку.
Если есть понятие сессии с клиентом и хост в начале может передать какие то уникальные данные сессии (SID + еще что то типа password_salt) до прикладного handshake, то клиент отправит hash(hash(password || username) || SID) или как дополнение предыдущего варианта hash(hash(password || username) || SID || client_salt) + client_salt
В общем вариантов много, в зависимости от конкретной задачи. Вариантов, что бы сделать как минимум данные авторизации в трафике эфемерными (что бы уменьшить потери при их перехвате и дискредитации)

redfox0
06.11.2026 02:34На IT happens была история, когда программисты реализовывали свою хеш функцию md5 и случайно написали её с ошибкой. Когда хеши паролей всё же утекли из базы, сбрутофорсенные пароли - по правильному алгоритму md5 - просто не подошли.

mmMike
06.11.2026 02:34Стандартные либы это хорошо. Но то же не панацея. И тут палка от двух концах
Вероятность что будет ошибка меньше (ну надежда на это больше)
Вероятность того что ее найдут - больше (исходники доступны всем, а твой личный пет проект никому даром не нужен). И то что уязвимостью сразу воспользуются то же больше.
Хотя утверждается, что полагаться на стойкость ПО/алгоритма исходя из того что он “секретен” нельзя (и MD5 и Mifare1 и ранний GSM A5 - примеры этого), но… обстоятельства разные.
В общем для чего то серьезного лучше выбрать нормальные более менее стандартизированные подходы. Но без профанации “а ключик тут спрячем в файле и зашифруем константным <ключем>, зашитым в коде”

devphp
06.11.2026 02:34Да, да.. та к это же та самая ситуация когда ситуёвина, когда два разных набора данных (например, two разных пароля или two разных файла) дают одинаковый хеш... ну а что тут скажешь.. 128бит все таки растояние не очень велико

16-bit-cat Автор
06.11.2026 02:34Вариантов много разного уровня безопасности. Я исходил из принципа "что угодно лучше чем ничего". Тут главное начать. Дальше уже должен триггериться внутренний перфекционист, и в попытках сделать нормально обнаруживать, что всё уже придумано до нас.

RulenBagdasis
06.11.2026 02:34Соль должна буть у каждого аккаунта своя а не одна на весь ресурс, чтобы радужные таблицы сложнее было строить. Но я согласен с тем, что передача хэшированного пароля не безопаснее передачи просто пароля. Риски все те же, если исходить из того, что юзер не использует один и тот же пароль на куче реурсов.

16-bit-cat Автор
06.11.2026 02:34Это все описано про соль из логина и домена. Модель угроз на самом деле сокращается. Разница есть.

WatchMaster
06.11.2026 02:34Мне кажется в статье не освещено ради чего мы усложняем систему и добавляем точек отказа. Нужна статистика от какого процента случаев кражи пароля мы защищаемся. Вот например тут https://deepstrike.io/blog/compromised-credential-statistics-2025, написано, что это не более 7 процентов, но там отсылка на доклад ibm, т.е. надо понимать что этот процент зависит еще и от размера компании. Основные способы кражи паролей происходят до сервера и даже до клиентского хеширования, можно глянуть там же или поискать другие статьи на тему. А если так, то мы усложняем "горячий путь" ради 7ми процентов случаев, оно точно того стоит? Резюмируя, прежде чем идти усложнять систему ради сокращения случая внутренних краж, я бы более детально изучил, какой процент случаев мы таким образом хотим исключить.

16-bit-cat Автор
06.11.2026 02:34Любая подобная статистика основана на ошибке выжившего. Мы никогда не узнаем сколько было успешных взломов где следы удалось замести. Только я за свою жизнь сталкивался минимум с тремя успешными атаками на свой сервер, и то только из тех что обнаружил. Ни в какую статистику они не попали. А сколько таких ещё?
Да и просто захешировать пароль - не такое уж усложнение даже ради 7 процентов.
Другое дело - когда нужно исправить то что работает. Тут наверное придётся как-то оценивать. Честно говоря, без понятия как.

becefi
06.11.2026 02:34ОТР забыли в списке.

16-bit-cat Автор
06.11.2026 02:34Это отдельная тема.

becefi
06.11.2026 02:34Я имею ввиду не приложения\расширения для ОТР, а саму схему: SHA(secret + timestamp).

16-bit-cat Автор
06.11.2026 02:34Вариантов спасти пароль очень много, не один десяток. В итоге решил оставить только минимальный и актуальный варианты. Между ними можно выбрать на любой вкус. В конце концов мне за это не платят - просто хотел привлечь внимание к проблеме открытых паролей, а для её решения и простой хеш сойдёт.

event1
06.11.2026 02:34Если не хочешь вникать в «эти ваши непонятные протоколы», делай хотя бы хеширование на фронте.
При хешировании на фронте, хеш становится секретом и он хранится в базе сервера в явном виде. Иначе, как вредительским, такой совет назвать нельзя.

svirpen
06.11.2026 02:34я так понял, автор рекомендует хотя бы извлекать хэш на клиенте, и отправлять хэш вместо пароля на сервер, где от него еще раз извлекается хэш и записывается в БД

event1
06.11.2026 02:34И чем это лучше, чем отправлять пароль? Подслушивающий супостат увидит случайные буквы-цифры и испугается?

fedorro
06.11.2026 02:34Всякие Passkeys / WebAuthn — это отдельный дивный мир. Рассматривать его в рамках этой статьи не вижу смысла.
И зря - как раз общепринятые удобные стандарты, призванные убрать вот эти недостатки паролей.

iroln
06.11.2026 02:34убрать вот эти недостатки паролей
Удобно в двух случаях: ваш юзер продвинутый и понимает, что такое passkey, использует менеджер паролей/аппаратный ключ/другой девайс для аутентификации, и второй случай - это корпоративный юзер с одним компьютером.
Попробуй объясни обычному пользователю, как ему зайти в свой аккаунт на компьютере друга, когда его passkey там куда у него сейчас нет доступа.

inkelyad
06.11.2026 02:34Попробуй объясни обычному пользователю, как ему зайти в свой аккаунт на компьютере друга, когда его passkey там куда у него сейчас нет доступа.
"Никак. Ты же физическую дверь тоже открыть не можешь, если у тебя ключа нет?"
Это свойство, кстати, что требуется физический артефакт(телефон или токен) - во многих случаях весьма полезно.
Ну и сам сценарий, ну такой. "Зайти в сервис а компьютере друга" - легко и непринужденно превращается в "зайти в сервис на непонятном компе" (в экстремальных случаях - вообще, на компе мошенника). Где всякие кейлоггеры, фишинговые прокладки и прочие неприятности живут. Именно с этим вариантом, как бы, бороться и пытаются, призывая отказываться от паролей.

16-bit-cat Автор
06.11.2026 02:34В обстоятельствах, где твоей собственностью могут завладеть по щелчку пальцев те кого на это уполномочили, или кто уполномочил себя сам - надёжнее двигаться в сторону паролей и правдоподобного отрицания, а не материального ключа. Хотя конечно зависит от ресурса, который защищается. Я бы и правда не хотел вводить пароль от многих ресурсов, но где-то никогда бы не хотел от этого отказываться. И там и там есть свои минусы и плюсы. Это параллельные способы, ни один не лучше и не хуже, и часто дополняют друг друга в виде 2FA.

inkelyad
06.11.2026 02:34в cторону паролей и правдоподобного отрицания, а не материального ключа.
Если учитывать эту угрозу - то в сторону материального ключа, который хочет пароля? А пока не введешь(желательно прямо на нем) - все зашифровано.
Ну и это ни разу не в контексте 'обычного человека'. Если он будет двигаться в сторону паролей, то он просто будет этот пароль переиспользовать, что в контексте этой угрозы - только хуже сделает.

iroln
06.11.2026 02:34Хеширование пароля на клиенте
Плохой совет, создающий ложное чувство безопасности. Тот, кто завладел хешем сможет сам передавать на этот сервер этот хеш, то есть сам хеш становится секретом аутентификации. Так что лучше так не делать, даже учитывая определённые плюсы в плане “я человек простой, у меня один пароль от всего интернета”.
Не надо делать ерунду, надо сразу использовать всякие PAKE и OPAQUE если не хотите передавать пароль в открытом виде.
В подавляющем большинстве продакшн‑инфраструктур TLS терминируется на балансировщике
Не знаю, где это подавляющее большинство, но нигде в своей практике такого не встречал, всегда решали делать шифрование внутри инфраструктуры, несмотря на накладные расходы.

16-bit-cat Автор
06.11.2026 02:34Реальность такова, что есть определенный порог входа или мотивационный... короче я бы предпочёл в 80% видеть хороший хеш, чем только в 20% полноценный PAKE, а в остальных случаях простой пароль. Это желание исходит от того, что mitm я еще могу как то контроллировать, а утечку с чужого сервера - нет.
В идеале конечно да, кто спорит, надо делать правильно сразу.
Насчёт иллюзии безопасности хеша погуглите скорость перебора Argon2. На фронте повышается длина секрета, и дальше на сервере можно применять уже более дешевый хеш, и удачи тому кто решит перебирать входы длиной с хеш, вышедший с фронта. То есть подбирать можно только сразу всю цепочку без возможности ускориться. Нагрузка при этом ложится на клиента, а не на сервер. Это я опять же про утечку данных, а не про кражу сессии.

becefi
06.11.2026 02:34Вы говорите ерунду. В таких схемах пароль используется в связке с nonce, передаваемом с сервера и/или timestamp. Завладение хешем не дает ничего.

16-bit-cat Автор
06.11.2026 02:34Добавлю пожалуй пару строк в текст. Судя по всему я зря оборвал и перешёл сразу к протоколам.

Xokare
06.11.2026 02:34Всё это совершенно бесполезно пока любой пароль можно сбросить просто перейдя по ссылке из email. В лучшем случае - по коду из СМС. Коль так, то и смысла городить нет. Беспарольная аутентификация по ссылке из email наше всё.

16-bit-cat Автор
06.11.2026 02:34Это параллельный великолепный способ, никто не спорит. Аутентификация просто переносится в другое место, в данном случае на оператора связи. Это даёт зависимость от третьих лиц, подверженность санкциям и риск утраты доступа. Но статья конкретно про пароль и его спасение. Для паролефилов.
Сброс пароля не компрометирует пароль пользователя (за исключением случая, когда при указании нового пароля система запрещает ввести старый пароль - за такое нужно увольнять сразу, имхо).
Посыл в том, что пользователю абсолютно плевать на дырявый сайт и его судьбу, ему важно чтобы с него не утёк его пароль, т.к. это вызовет для него некоторые неудобства.

becefi
06.11.2026 02:34аутентификация по ссылке из email - это зло.
1. вместо одного сервиса нужно логиниться в 2
2. завладев доступом к одному сервису (почта) злоумышленник получает автоматически доступ ко всем (кто таким образом аутентифицирует)
inkelyad
06.11.2026 02:342. завладев доступом к одному сервису (почта) злоумышленник получает автоматически доступ ко всем (кто таким образом аутентифицирует)
Это почти всегда так. Потому что "восстановить доступ" - это и есть аутентификация по ссылке, если аккуратно 2FA не сделана (как у гугла, например - там при включенной ссылки из email не хватит)
А "логинится в два сервиса" - ну так по умолчанию предполагается, что почтовый интерфейс всегда доступен, отдельно логинится в него не надо.
nojecom
а что есть "правильный" пароль? Какой-нибудь задрищенский сайт с посещаемостью 2 человека в месяц просит в пароле буквы, цифры, символы, две кракозябры, китайские иероглифы и символы верхнего юникода, а в банк-клиенте пароль с пробелом - ни-ни, нельзя пробел, только латиницу и цифры.
Идеально - вообще никак не вмешиваться в построение пароля. Хочу 111 - значит будьте добры его принять, хочу ☋6d+86J ⁂}࿘∀⏩⤦ - тоже принимайте. Не надо мне рассказывать, где нехватает символов, а где они лишние. Просто перестаньте выдумывать требования к паролю.
16-bit-cat Автор
Все эти ограничения ещё и уменьшают пространство поиска при брутфорсе.
Самые упоротые (типа VK) ещё и запрещают менять пароль на старый после процедуры сброса пароля. Во-первых значит они их все хранят (надеюсь что хотя бы хеши), во вторых это только способствует забыванию каждого нового. Что там в головах у людей...