Серверов два — сервер авторизации и сервер игры. Каждый из них шифрует пакеты для клиента немного по-своему
Поскольку в ответ на 0x00 (Init) ожидается ответ 0x07 (AuthGameGuard), значит речь идет о сервере авторизации. Рассмотрим общение с клиентом на примере сервера авторизации версии c621
Общие сведения
- Сервер авторизации версии c621 совместим с клиентами Chaotic Throne (включая и Interlude, и High Five), а так же, возможно, и с другими
- Если клиент получит от сервера неправильный пакет, он зависнет, кританет или не сделает ничего. Никаких уведомлений клиент не присылает
- Пакеты представляют собой массивы байтов
- В TCP-сокет байты приходят и записываются в обратном порядке (см. Little Endian)
- Пакеты состоят из длины (2 байта), типа пакета (1 байт) и содержимого (любое число байтов)
- Содержимым пакета будем называть именно данные, передаваемые в пакете (ключи, ID сессии и т.д.), исключая длину и тип пакета
- Длина пакета не шифруется и не учитывается при подсчёте контрольной суммы, поскольку вычисляется после. Тип пакета, как и содержимое, учитывается при подсчёте контрольной суммы. Тип пакета, содержимое и контрольная сумма шифруются вместе по алгоритму Blowfish
- Длина пакета — число, обозначающее длину всего пакета. Иными словами, в нее включаются и длина зашифрованных данных (которые состоят из содержимого и типа пакета, контрольной суммы и зашифрованы по алгоритму Blowfish) и два байта на само число, указывающее длину
- Blowfish — блочный алгоритм шифрования, обрабатывает блоками по 8 байт, а значит, длина содержимого пакета вместе с типом и контрольной суммой должна быть кратна 8 (для этого контрольная сумма отбивается от содержимого пакета необходимым количеством нулей)
- Обратите внимание, в зависимости от того, заранее ли вы собираете пакет в порядке Little Endian или потом разворачиваете алгоритмы шифрования и расчета контрольной суммы будут, соответственно, разными
Это может быть важно в том случае, если, к примеру, выбранная для вашего языка программирования библиотека Blowfish может шифровать байты только в прямом порядке (Big Endian)
Порядок взаимодействия сервера авторизации с клиентом
Для удобства обозначим префиксом S пакеты, отправляемые сервером, а C — присылаемые клиентом, поскольку они могут иметь одинаковые ID, но разное содержимое
Пакет S/0x00 (Init) не подписывается контрольной суммой, все остальные пакеты подписываются
Пакет S/0x00 (Init) шифруется по алгоритму XOR, все остальные пакеты не шифруются
Все пакеты шифруются по по алгориму Blowfish ключом, случайно генерируемым для каждого подключения и отправляемым в пакете S/0x00 (Init), кроме самого пакета S/0x00 (Init), который шифруется ключом, придуманным разработчиками игры (зашит в клиенте)
Шифрование по алгоритму Blowfish всегда идет последним, т.е.:
Код:
# Шифрование пакета S/0x00 (Init)
data = xor.encrypt(data)
data = blowfish.encrypt(data, STATIC_KEY)
# Шифрование любого другого пакета
data = checksum.sign(data)
data = blowfish.encrypt(data, SESSION_KEY)
Расшифровка всегда идет одинаково:
Код:
# Расшифровка любого входящего пакета
data = blowfish.decrypt(data, SESSION_KEY)
data = checksum.verify(data)
Содержимое пакета C/0x00 (RequestAuthLogin) приходит зашифрованным алгоритмом RSA тем ключом, который сервер отправляет в пакете S/0x00 (Init). Зашифрованным приходит только содержимое, но не длина и не тип пакета. Сам пакет зашифрован как обычно. Содержимое зашифровано дополнительно, т.к. содержит логин и пароль
Порядок взаимодействия при успешной авторизации:
- Пользователь вводит логин и пароль, нажимает вход
- Клиент подключается к серверу
- Сервер отправляет пакет S/0x00 (Init)
- Клиент присылает пакет C/0x07 (AuthGameGuard)
- Сервер отправляет пакет S/0x0b (GGAuth)
- Клиент присылает логин и пароль в пакетe C/0x00 (RequestAuthLogin)
- Сервер проверяет логин и пароль и отправляет S/0x03 (LoginOk)
- Клиент запрашивает список игровых серверов пакетом C/0x05 (RequestServerList)
- Сервер отправляет список игровых серверов в пакете S/0x04 (ServerList)
- Пользователь выбирает сервер из списка, нажимает вход
- Клиент присылает пакет C/0x02 (RequestServerLogin)
- Сервер отправляет пакет S/0x07 (PlayOK)
Далее клиент отключается от сервера авторизации и подключается к игровому серверу
Отправка пакетов сервером авторизации
Пакеты записываются в виде массива байтов:
- Записываем 1 байт типа пакета, например, 0x00
- Формируем и дописываем содержимое пакета (ID сессии, версию сервера, ключи, нулевой байт окончания ключа Blowfish и т.д.)
- Вычисляем контрольную сумму для текущего массива байт
- Добиваем длину текущего массива байт нулевыми байтами до кратной 8
- Дописываем контрольную сумму в массив
- Шифруем текущий массив байт по алгоритму Blowfish
- Вычисляем длину получившегося массива
- Прибавляем к значению длины 2 для учета самих двух байтов длины
- Дописываем длину в начало массива
В TCP-сокет байты следует записывать в обратном порядке
Получение пакетов сервером авторизации
Пакеты считываются из массива байтов:
- Считываем 2 байта длины пакета
- Вычитаем 2 из значения длины, чтобы отсечь байты самой длины
- Считываем получившееся число байт в отдельный массив для данных
- Расшифровываем байты данных по алгоритму Blowfish
- Вычисляем и сверяем контрольную сумму
- Отсекаем один байт с типом пакета
- Разбираем байты содержимого
Из TCP-сокета байты следует считывать в обратном порядке