Протокол безопасности для генерации общего секретного ключа на стороне сервера
Я пытаюсь реализовать систему безопасности, которая имеет следующие требования:
- Все клиенты имеют общий пароль, который неизвестен серверу
- Каждый клиент имеет уникальный идентификатор клиента, который известен серверу
- Все клиенты со знанием пароля должны иметь возможность генерировать один и тот же общий секрет на сервере (этот секрет может быть любым, он просто должен быть одинаковым для всех клиентов и уникальным для всех паролей)
- Пароль должен оставаться безопасным, даже если сервер или транспорт взломаны
- Для другой стороны с другим идентификатором клиента должна быть невозможна генерация того же секрета на стороне сервера без знания пароля
Позвольте мне попытаться дать графическое представление этого:
Client Server
.--------------^-----------. .----------^----------.
f(client-id 1) g(client-id 1)
PASSWORD ----------------> request 1 ----------------> KEY
|| equal || equal
PASSWORD ----------------> request 2 ----------------> KEY
f(client-id 2) g(client-id 2)
Здесь f() [g()] - это функции, которые клиент [сервер] применяет к паролю [запрос] для получения запроса [ключ]. Эти функции могут зависеть от идентификатора клиента.
Есть два подхода, которые я мог бы предложить, которые могли бы сделать это, но я надеюсь на что-то более простое, требующее меньшего трафика и меньшей нагрузки на сервер:
"Легко понять": клиенты хэшируют пароль. Каждый клиент и сервер используют стандартный механизм (например, SSL) для защиты своего соединения и отправки хэша по этому соединению.
"Немного умнее": на сервере закодирован фиксированный закрытый ключ, а каждому клиенту закодирован открытый ключ. Клиенты хешируют пароль, XOR его со своим идентификатором клиента, шифруют результат с помощью RSA/PGP с использованием открытого ключа. Затем сервер расшифровывает запрос, используя закрытый ключ, и XOR-результат с идентификатором клиента для получения хэша пароля.
В обоих случаях сервер получает один и тот же секрет для клиентов: хэш пароля. Преимущество второй версии состоит в том, что нет необходимости в дополнительных издержках полноценной системы обмена ключами и шифрования, поскольку, к сожалению, я не смогу полагаться на SSL во всех случаях. Фактически, это позволяет мне генерировать секрет сервера в одном запросе без какого-либо рукопожатия. Client-id-XOR во второй версии используются для предотвращения повторных атак, когда в противном случае третье лицо с другим идентификатором клиента может просто отправить одно и то же зашифрованное сообщение на сервер, чтобы сгенерировать тот же секрет. По сути, это простой способ добавить соль.
Теперь вопрос:
Поскольку у меня нет никаких требований к секрету на стороне сервера, даже то, что клиенты могут генерировать этот секрет локально, есть еще более простой способ сделать это, не требующий дорогого модульного возведения в степень чисел произвольной точности, таких как RSA делает? Я имею в виду, может быть, какую-то другую функцию люка для f () и g () выше, которая позволяет мне достичь того же результата.
1 ответ
Наверное, не берутся... Вопрос, вероятно, слишком расплывчатый...
В любом случае: сейчас я решил использовать RSA (т.е. подход 2 сверху). Это достаточно просто для реализации и с правильными библиотеками, это не слишком дорого для запуска.