Протокол защищенного удаленного пароля (SRP ) является расширенным протокол согласования ключей с аутентификацией паролем (PAKE), специально разработанный для обхода существующих патентов.
Как и все протоколы PAKE, перехватчик или посредник не может получить достаточно информации чтобы иметь возможность подбирать пароль без дальнейшего взаимодействия со сторонами для каждого предположения. Кроме того, поскольку это расширенный протокол PAKE, сервер не хранит данные, эквивалентные паролю. Это означает, что злоумышленник, который крадет данные сервера, не может маскироваться под клиента, если сначала он не выполнит поиск пароля методом грубой силы.
С точки зрения непрофессионала, во время аутентификации SRP (или любого другого протокола PAKE) одна сторона («клиент» или «пользователь») демонстрирует другой стороне («серверу»), что они знают пароль, без отправка самого пароля или любой другой информации, на основе которой может быть получен пароль. Пароль никогда не покидает клиента и неизвестен серверу.
Кроме того, серверу также необходимо знать пароль (но не сам пароль), чтобы установить безопасное соединение. Это означает, что сервер также аутентифицируется для клиента, не полагаясь на то, что пользователь анализирует сложные URL-адреса. Это предотвращает фишинг.
Протокол SRP имеет ряд желательных свойств: он позволяет пользователю аутентифицироваться на сервер, он устойчив к атакам по словарю, установленным перехватчиком, и не требует доверенной третьей стороны. Он эффективно передает пароль с нулевым разглашением от пользователя к серверу. В 6-й версии протокола можно угадать только один пароль за попытку подключения. Одним из интересных свойств протокола является то, что даже если один или два криптографических примитива, которые он использует, подвергнутся атаке, он по-прежнему безопасен. Протокол SRP пересматривался несколько раз и в настоящее время находится на доработке 6a.
Протокол SRP создает большой закрытый ключ, совместно используемый двумя сторонами, аналогично обмену ключами Диффи – Хеллмана на основе клиентской стороны, имеющей пароль пользователя, а на стороне сервера - криптографический верификатор, полученный из пароля. Общий открытый ключ получается из двух случайных чисел, одно сгенерированное клиентом, а другое сгенерированное сервером, которые уникальны для попытки входа в систему. В случаях, когда требуется шифрованная связь, а также аутентификация, протокол SRP более безопасен, чем альтернативный протокол SSH, и быстрее, чем использование обмена ключами Диффи – Хеллмана с подписанными сообщениями. Он также не зависит от третьих лиц, в отличие от Kerberos. Протокол SRP версии 3 описан в RFC 2945. SRP версии 6 также используется для надежной парольной аутентификации в SSL / TLS (в TLS-SRP ) и других стандартах, таких как EAP и SAML и стандартизируется в IEEE P1363 и ISO / IEC 11770-4.
В этом описании протокола используется следующая нотация, версия 6:
Все другие переменные определяются в их терминах.
Во-первых, чтобы установить пароль p с сервером Steve, клиент Кэрол выбирает небольшой случайный salt s и вычисляет x = H (s, p), v = g. Стив хранит v и s, проиндексированные I, как средство проверки пароля Кэрол и соль. Кэрол не должна делиться x с кем-либо и должна безопасно стереть его на этом этапе, потому что он эквивалентен паролю p в виде открытого текста. Этот шаг выполняется до того, как система будет использоваться как часть регистрации пользователя у Стива. Обратите внимание, что соль s совместно используется и обменивается для согласования ключа сеанса позже, чтобы значение могло быть выбрано любой стороной, но это делает Кэрол, чтобы она могла зарегистрировать I, s и v в одном запросе регистрации. Передача и аутентификация запроса на регистрацию не рассматриваются в SRP.
Затем, чтобы выполнить подтверждение пароля позже, используется следующий протокол обмена:
Теперь у двух сторон есть общий надежный сеансовый ключ K. Для завершения аутентификации им необходимо доказать друг другу, что их ключи совпадают. Один из возможных способов следующий:
Этот метод требует угадывать больше общего состояния, чтобы быть успешным в олицетворении, чем просто ключ. Хотя большая часть дополнительного состояния является общедоступным, частная информация может быть безопасно добавлена во входные данные хэш-функции, например, закрытый ключ сервера.
В качестве альтернативы, только для подтверждения пароля вычисление K можно пропустить, а общий S проверить с помощью:
. При использовании SRP для согласования общего ключа K, который будет использоваться сразу после согласования, этапы проверки M 1 и M 2 могут быть пропущены. Сервер отклонит самый первый запрос от клиента, который он не может расшифровать. Пропуск этапов проверки может быть опасным.
Обе стороны также используют следующие меры предосторожности:
# Пример аутентификации SRP # ПРЕДУПРЕЖДЕНИЕ: не используйте для реальных криптографических целей, кроме тестирования. # ПРЕДУПРЕЖДЕНИЕ. В приведенном ниже коде отсутствуют важные меры безопасности. Он не проверяет, что A, B и U не равны нулю. # на основе http://srp.stanford.edu/design.html import hashlib import random def global_print (* names) ->None: x = lambda s: ["{}", "0x {: x}"] [ hasattr (s, "real")]. format (s) print ("". join ("{} = {} \ n".format (name, x (globals () [name])) для имени в именах)) # Примечание: str преобразуется как есть, str ([1,2,3,4]) преобразуется в "[1,2,3,4]" def H (* args) ->int: "" "A one -way хеш-функция. "" "a =": ". join (str (a) for a in args) return int (hashlib.sha256 (a.encode (" utf-8 ")). hexdigest (), 16) def cryptrand (n: int = 1024): return random.SystemRandom (). getrandbits (n)% N # Большое безопасное простое число (N = 2q + 1, где q - простое число) # Вся арифметика выполняется по модулю N # (генерируется используя "openssl dhparam -text 1024") N = "" "00: c0: 37: c3: 75: 88: b4: 32: 98: 87: e6: 1c: 2d: a3: 32: 4b: 1b: a4: b8: 1a: 63: f9: 74: 8f: ed: 2d: 8a: 41: 0c: 2f: c2: 1b: 12: 32: f0: d3: bf: a0: 24: 27: 6c: fd: 88: 44:81: 97: aa: e4: 86: a6: 3b: fc: a7: b8: bf: 77: 54: df: b3: 27: c7: 20: 1f: 6f: d1: 7f: d7: fd: 74: 15: 8b: d3: 1c: e7: 72: c9: f5: f8: ab: 58: 45: 48: a9: 9a: 75: 9b: 5a: 2c: 05: 32: 16: 2b: 7b: 62: 18: e8: f1: 42: bc: e2: c3: 0d: 77 : 84: 68: 9a: 48: 3e: 09: 5e: 70: 16: 18: 43: 79: 13: a8: c3: 9c: 3d: d0: d4: ca: 3c: 50: 0b: 88: 5f : e3 "" "N = int (" ". join (N.split ()). replace (": "," "), 16) g = 2 # Генератор по модулю N k = H (N, g) # Параметр множителя (k = 3 в устаревшей SRP-6) print ("#. H, N, g и k известны заранее как клиенту, так и серверу: ") global_print (" H "," N "," g "," k ") print (" 0. Сервер хранит (I, s, v) в своей базе паролей ") # Сервер должен сначала сгенерировать верификатор пароля I =" person "# Имя пользователя p =" password1234 "# Пароль s = cryptrand (64) # Соль для пользователя x = H (s, I, p) # Закрытый ключ v = pow (g, x, N) # Средство проверки пароля global_print ("I", "p", "s", "x", "v") print ("1. Клиент отправляет имя пользователя I и общедоступный эфемерное значение A на сервер ") a = cryptrand () A = pow (g, a, N) global_print (" I "," A ") # client->server (I, A) print (" 2. Сервер отправляет соль пользователя s и общедоступное эфемерное значение B для клиента ") b = cryptrand () B = (k * v + pow (g, b, N))% N global_print (" s "," B ") # server->client (s, B) print («3. Клиент и сервер вычисляют параметр случайного скремблирования») u = H (A, B) # Параметр случайного скремблирования global_print («u») print («4. Клиент вычисляет сеансовый ключ») x = H (s, I, p) S_c = pow (B - k * pow (g, x, N), a + u * x, N) K_c = H (S_c) global_print ( «S_c», «K_c») print («5. сервер вычисляет сеансовый ключ ") S_s = pow (A * pow (v, u, N), b, N) K_s = H (S_s) global_print (" S_s "," K_s ") print (" 6. Клиент отправляет подтверждение ключ сеанса к серверу ") M_c = H (H (N) ^ H (g), H (I), s, A, B, K_c) global_print (" M_c ") # client->server (M_c); сервер проверяет M_c print («7. сервер отправляет подтверждение сеансового ключа клиенту») M_s = H (A, M_c, K_s) global_print («M_s») # server->client (M_s); клиент проверяет M_s
# Н, N, г, и к заранее известны как для клиента и сервера:. H =N = 0xc037c37588b4329887e61c2da3324b1ba4b81a63f9748fed2d8a410c2fc21b1232f0d3bfa024276cfd88448197aae486a63bfca7b8bf7754dfb327c7201f6fd17fd7fd74158bd31ce772c9f5f8ab584548a99a759b5a2c0532162b7b6218e8f142bce2c30d7784689a483e095e701618437913a8c39c3dd0d4ca3c500b885fe3 г = 0x2 к = 0. 0xb317ec553cb1a52201d79b7c12d4b665d0dc234fdbfd5a06894c1a194f818c4a сервер хранит (I, S, V) в ее база данных паролей I = человек p = пароль1234 s = 0x23c52769f89b02c0 x = 0x28a914ef69978f5fe544f030bea89eab675bcaa2ec79c d36efa1d410d27d5215 v = 0xa636254492ec0f7391d6b596ec926b91866775072dfd758c6ebc51bf7277ec6ca97f6cf0316d7fa90a2b9e87366cf813a53dcdc6ab303fcc932a5783f62affb7e0275189f165b8b919a2067404e6f2aa0534c99a3224a6365c1367dcd9ef005376d6f20a2b300c307f7afcedea08fb2d7a3340f13b5b9e35d52f0b82670ab17e 1. клиент отправляет имя пользователя I и общественное эфемерное значение А на сервер I = человек A = 0x48147d013e3a2e08ace222a0ab914a7ed67c704b2480716b53f9d229243d1725473cf4451904658597f487b0fa8bc7d544671b25563f095bad384cbb8da7f58f7f13c8fa8bb9d6aade5fe02df288f2b38d71d51036ede52802645f82cd7216535c0c978f90230e0f878163a638cf57ad11968169c26e467b8ee14eb2ca5b1614 2. Сервер отправляет соль пользователя s и общественное эфемерное значение B до S = 0x23c52769f89b02c0 B = 0x709f340738e62e46184634acd2cd7c861a7d92c5fde9eb43ac120226a0eb6601ee5d1a0b92ffb6254170d91fb451c3c02bbf8b41f9e7e3e885d709f0dc4808048e595c68448a2111b45eefaa1e2d6a4814d99ae038a5f2371c753b312c529cada66b23e6512c7ef814683f4cfe2a4c5413c434e21bc689d869fc969141b84a61 3. клиента клиента и серв эр вычислить случайное скремблирование параметра и = 0x78e4f2723b9ee5f69c7225469c70263cb39580dd4414b82ab9960def0ac9ef68 4. клиентского ключа сеанса вычисляет S_c = 0x94ea4b72b61d4330cf44f31e5c710491d41abdd6dd5b66b277bc517addbe89d9aa002645897567ae7796d1574f5d7f62cf96d2246dabfbc919cf1444d69097ceaf5476bc3964cacd52697e346f5e5a424c2c89b661d2eba34e5c7195573442195611497f606fa49639f873f385d0f6cdb9308fe2b0777d1a89bbaebe9df237a4 K_c = 0x3f1e089e02b3770a5e4ab27b3a04415e54826fe4b729cd37b86fbe59b9e0d3c6 5. Сервер вычисляет ключ сеанса S_S = 0x94ea4b72b61d4330cf44f31e5c710491d41abdd6dd5b66b277bc517addbe89d9aa002645897567ae7796d1574f5d7f62cf96d2246dabfbc919cf1444d69097ceaf5476bc3964cacd52697e346f5e5a424c2c89b661d2eba34e5c7195573442195611497f606fa49639f873f385d0f6cdb9308fe2b0777d1a89bbaebe9df237a4 K_S = 0x3f1e089e02b3770a5e4ab27b3a04415e54826fe4b729cd37b86fbe59b9e0d3c6 6. Клиент посылает подтверждение ключа сеанса на сервер M_C = 0x21d1546a18f923907b975091341316ca03bacf9cfd61b33f66d87e07eacff18 7. Сервер отправляет доказательство этого ssion key для клиента M_s = 0x937ee2752d2d0a18eea2e7d4c5aa0dd0df54970f4c99fc13c75c5db3bba45643