У меня есть игра клиент-сервер, где клиент подключается к серверу и остается подключенным во время игры (около 5-60 минут).
Я хочу, чтобы новые клиенты могли безопасно регистрироваться, а также чтобы существующие клиенты могли проходить аутентификацию, не беспокоясь о том, что учетные данные для входа будут открыты.
Дело в том, что по соображениям производительности было бы лучше придерживаться простого и дешевого шифрования, такого как RC4, для игрового сеанса, но симметричный ключ не упрощает процедуру регистрации.
Поскольку я все равно хочу сохранить отдельный сервер входа в систему, моя идея такая:
- Клиент отправляет HTTPS-запрос на сервер входа с учетными данными (или регистрационной информацией)
- Сервер входа в систему собирает информацию о пользователе и генерирует временный ключ шифрования сеанса RC4.
- Информация о пользователе + сеанс RC4 + временная метка + дайджест (я могу рассчитывать на синхронизацию обоих серверов по времени) с секретным симметричным ключом, совместно используемым игровым сервером и сервером входа в систему.
- Упакованные данные + ключ шифрования сеанса RC4 + IP-адрес игровому серверу отправляются в качестве ответа на запрос HTTPS клиенту.
- Клиент открывает соединение с игровым сервером, отправляет начальное незашифрованное приветственное сообщение с зашифрованной информацией о пользователе в качестве полезной нагрузки.
- Игровой сервер распаковывает данные, упакованные в (3). Теперь он знает пользователя и ключ шифрования RC4, который предполагается использовать.
- Если временная метка указывает, что срок действия учетных данных для входа истек, клиенту возвращается ошибка (который затем должен получить новую информацию). Если расшифрованные данные пользователя не могут быть проверены с помощью дайджеста, возвращается другая ошибка.
- Если все проходит нормально, сервер отправляет незашифрованный LOGIN_OK, и начинается зашифрованный обмен данными RC4.
Возможные проблемы безопасности:
Игровой сервер на 100% доверяет расшифрованной им информации о пользователе. Это делает серверы полностью разделенными, что приятно, но если ключ будет скомпрометирован, пользователи могут полностью подделать свою информацию о пользователе. Это можно было бы несколько смягчить, повернув эти клавиши так, чтобы каждый день или месяц появлялся новый ключ. И игровой сервер, и сервер входа в систему могут получить это от третьего сервера, который управляет их ключами. Это может быть излишним, поскольку: а) в случае взлома, когда исходный код открыт на серверах, они могут быть перезапущены с новым ключом б) достаточно хороший ключ + шифрование должно усложнять атаки методом грубой силы (предложения по алгоритму ?)
RC4 - не самый безопасный алгоритм, но я обязательно выбрасываю первые 512 байтов или около того, и каждый ключ действителен только в течение ограниченного времени, например 24ч.
Из того, что я вижу, не кажется уязвимым для посредников: SSL защищает сеансовый ключ RC4, в (5) сеансовый ключ RC4, отправляемый на игровой сервер, также зашифрован. Все, что возможно, - это DoS и заставить пользователя снова запросить ключ. Если данные в (2) кэшируются до истечения срока их действия, это не должно создавать новый пакет.
Шифрование в (3) можно улучшить, добавив к ключу случайные биты. Эти случайные биты отправляются вместе с зашифрованным пакетом и представляются игровому серверу в (5). В (6) игровой сервер добавляет эти случайные биты к своему ключу и использует результат для расшифровки данных. Таким образом, злоумышленник не сможет увидеть изменения упакованных данных.
Есть ли какие-то уязвимости, которые я здесь не замечаю?
Сводка созданных полезных нагрузок:
- Учетные данные клиента (защищенные SSL), отправленные на сервер входа
- Информация о пользователе + временная метка + временный ключ сеанса игрового сервера + дайджест, зашифрованный сервером входа с использованием секретного ключа, совместно используемого с игровым сервером, передается клиенту, который - без его изменения - передает его на игровой сервер. Должен быть устойчивым, потому что: a) клиент не знает секретный ключ; b) имеет метку времени, чтобы избежать повторной отправки тех же данных; c) дайджест для проверки правильности шифрования содержимого
- временный ключ сеанса игрового сервера, отправляемый сервером входа в систему клиенту вместе с зашифрованными данными. Защищено SSL.
- Пакет для входа на сервер клиентской игры, состоит из зашифрованного пакета, полученного сервером входа в систему.
Сводка ключей шифрования:
- Временный ключ сеанса игрового сервера: генерируется случайным образом сервером входа в систему для зашифрованной связи игрового сервера ‹-> с клиентом. Генерируется сервером входа в систему, передается клиенту и игровому серверу.
- Ключ шифрования секретной информации о пользователе. Распространяется между игровым сервером и сервером входа, используется для передачи информации о пользователе на игровой сервер с клиентом в качестве мессенджера. У клиента нет этого ключа.