Протокол аутентификации без разглашения
Secure Remote Password Protocol (SRPP) — одно из последних пополнений в семействе протоколов аутентификации, устойчивых ко всем известным видам активных и пассивных сетевых атак. SRP берет некоторые элементы из других протоколов обмена ключами и идентификации, при этом внося небольшие усовершенствования и уточнения. В результате мы получаем протокол, сохраняющий стойкость и эффективность протоколов класса Encrypted key exchange, при этом избавляясь от некоторых их недостатков.
Протокол SRP позволяет пользователю идентифицировать себя на сервере, при этом не передавая своего пароля, то есть подтвердить тот факт, что он знает свой пароль, и только этот факт. Он имеет ряд полезных качеств:
· устойчив к атакам перебора по словарю при прослушивании канала предохраняет прошедшие сессии и пароли от будущего разглашения
· работает при условиях наличия канала, не только не защищенного от прослушивания, но и не защищенного от подмены
· не требует наличия какого-либо дополнительного защищённого канала.
· пользовательские пароли хранятся в формате, не эквивалентном открытому тексту пароля, так что злоумышленник, каким-либо образом получивший базу данных сервера, не может использовать её.
SRP эффективно реализует Доказательство с нулевым разглашением между пользователем и сервером, хранящим информацию о его пароле. При прослушивании за один раз злоумышленником может быть проверена только одна версия пароля, начиная с версии 6 данного протокола. Данный протокол имеет много ревизий, на данный момент последняя ревизия — 6a.
В результате работы данного протокола обе стороны получают длинный секретный ключ, проверяемый на соответствие между сторонами после получения. В случаях, когда помимо аутентификации необходимо шифрование данных, SRP предоставляет более надёжные, чем SSH, и более быстрые, чем Deffie-Hellman, средства для достижения этой цели. Протокол SRP версии 3 описывается в RFC 2945. SRP версии 6 также используется для аутентификации в SSL/TLS и других стандартах, таких как EAP и SAML, и в данный момент стандартизуется IEEE P1363 и ISO/IEC 11770-4.
Принцип работы
Введем обозначения, необходимые для рассуждения:
· q и N = 2q + 1 выбираются так, что N и q простые. N должно быть достаточно большим, чтобы дискретное логарифмирование по модулю N было практически неосуществимо.
· Вся арифметика выполняется по модулю N (поле ).
· g — генератор мультипликативной группы
· k — параметр, получаемый на обоих сторонах, например, k = H(N, g) в ревизии 6а (в ревизии 6 k было постоянным и равно 3).
· s — соль
· I — идентификатор пользователя в системе сервера (username).
· p — пароль пользователя, соответствующий I.
· H() — криптографическая хеш-функция, например, SHA-256
· x — секретный ключ, x = H(s, p).
· v — верификатор пароля на стороне сервера, v = gx.
· u — произвольный параметр для кодирования.
· a,b — секретные одноразовые числа
Понятия пароля и верификатора соответствуют общепринятым понятиям секретного и открытого ключей, с двумя оговорками: пароль, как правило, меньше секретного ключа, так как его помнит пользователь, а память у него небольшого размера; в свою очередь, верификатор по математическим свойствам схож с открытым ключом, так как он легко получается из пароля, а обратная операция является вычислительно неразрешимой. Однако вместо того, чтобы быть общеизвестным, верификатор хранится сервером в тайне. Способ аутентификации, который предполагает хранение сервером верификатора, но не пароля, называется основанным на верификации(verifier-based).
Из исходных параметров вычисляются A,B (см. ниже). Сервер хранит пароли, используя следующую формулу:
· x = H(s, p) (s выбирается произвольным образом)
· v = gx (вычисление верификатора пароля)
После этого сервер хранит пару (I, s, v) в своей базе данных. Аутентификация происходит по следующей схеме:
1. Клиент -> Сервер: I, A = ga (идентифицируется, a — произвольное)
2. Сервер -> Клиент: s, B = kv + gb (посылает сохраненное s, произвольное b)
На обоих сторонах: u = H(A, B) На стороне клиента:
1. x = H(s, p) (пользователь вводит пароль)
2. S = (B — kgx)(a + ux) (вычисляется ключ сессии)
3. K = H(S) (K — это искомый ключ для шифрования)
На стороне сервера:
1. S = (Avu)b (вычисление ключа сессии)
2. K = H(S) (K — это искомый ключ для шифрования)
Теперь обе стороны имеют общий секретный ключ K. Для завершения аутентификации, им необходимо свериться, что их ключи совпадают. Один из возможных способов:
Клиент -> Сервер: M = H(H(N) xor H(g), H(I), s, A, B, K) и проверка на стороне сервера
Сервер -> Клиент: H(A, M, K) и проверка на стороне клиента