Кстати мне функция send возвращает результат своей работы в виде - 50, что это я немогу понять? в описании ошибок нет цифр 50, есть 10000, 10050, 10051 и т.д.
Ну вобщем пока решил пакет ProtocolVersion оставить в том виде в каком его передает клиент, и не пытаться понять его суть...
Вернее насчет того, что клиент передает серверу информацию о своем протоколе - понятно.
Непонятно только смысл передаваемых 256 байт данных, начиная с 8-го... И непонятно то, почему у сервера своя нумерация протоколов, а у клиента своя... Ведь протокол - это вроде нечто общее, определяющее правила взаимодействия клиента и сервера.
Добавлено через 1 час 0 минут
Отправил пакет protocolVersion. Сервер мне прислал пакет с XOR-ключом.
А вот дальше пока возникла проблема с шифрованием:
Описание такое:
Код:
1.2. Шифрация пакетов GameServer'a:
Чтобы не загружать ваши и без того замученные головы, вместо алгоритмов, я дам готовые исходники (немного измененные для наглядности):
char key_sc[8];
char key_cs[8];
void Encrypt(char *raw, int size)
{
int temp = 0;
for (int i=0; i<size; i++)
{
int temp2 = raw[i] &0xff;
raw[i] = (char)(temp2 ^ (key_cs[i&7] &0xff) ^ temp);
temp = raw[i];
}
int old = key_cs[0] &0xff;
old |= key_cs[1] << 8 &0xff00;
old |= key_cs[2] << 0x10 &0xff0000;
old |= key_cs[3] << 0x18 &0xff000000;
old += size;
key_cs[0] = (char)(old &0xff);
key_cs[1] = (char)(old >> 0x08 &0xff);
key_cs[2] = (char)(old >> 0x10 &0xff);
key_cs[3] = (char)(old >> 0x18 &0xff);
}
void Decode(char *input, int size)
{
int i = 0;
int j = 0;
for(int k=0; k < size; k++)
{
int i1 = input[k] & 0xFF;
input[k] = (char)(i1 ^ key_sc[j++] & 0xFF ^i);
i = i1;
if(j>7) j=0;
}
long l = key_sc[0] & 0xFF;
l |= key_sc[1] << 8 & 0xFF00;
l |= key_sc[2] << 16 & 0xFF0000;
l |= key_sc[3] << 24 & 0xFF000000;
l += size;
key_sc[0] = (char)(l & 255L);
key_sc[1] = (char)(l >> 8 & 255L);
key_sc[2] = (char)(l >> 16 & 255L);
key_sc[3] = (char)(l >> 24 & 255L);
}
void Key(char* packet, int len)
{
key_sc[0] = packet[4];
key_sc[1] = packet[5];
key_sc[2] = packet[6];
key_sc[3] = packet[7];
key_sc[4] = (char)0xA1;
key_sc[5] = (char)0x6C;
key_sc[6] = (char)0x54;
key_sc[7] = (char)0x87;
for(i=0;i<8;i++) {key_cs[i]=key_sc[i];}
}
void add_ckecksum(unsigned char *raw, int count) //вычисляет чексумму и вставляет её в пакет
{ //как пользоватся: add_ckecksum(CelyjPaket+2, DlinaPaketa-(2+4+4));
unsigned long chksum = 0;
unsigned long ecx;
int i = 0;
for(i = 0; i < count; i += 4)
{
ecx = (unsigned long)raw[i];
ecx |= (unsigned long)raw[i + 1]<<8;
ecx |= (unsigned long)raw[i + 2]<<16;
ecx |= (unsigned long)raw[i + 3]<<24;
chksum ^= ecx;
}
memcpy(raw+count, (char *)&chksum, 4);
}
void RSAKeyDecode(char* RSAKey)
{
for (int i = 0; i < 64; i++)
{
RSAKey[i + 64] ^= RSAKey[i];
}
for (int i = 0; i < 4; i++)
{
RSAKey[i + 13] ^= RSAKey[i + 52];
}
for (int i = 0; i < 64; i++)
{
RSAKey[i] ^= RSAKey[i + 64];
}
for (int i = 0; i < 4; i++)
{
BYTE tmp = RSAKey[i];
RSAKey[i] = RSAKey[i + 77];
RSAKey[i + 77] = tmp;
}
}
Но сишный код мне очень трудно понять.
Может кто-нить на словах объяснить как идет шифрация/дешифрация и смена ключа?
Последний раз редактировалось glukmaker, 14.10.2011 в 13:47.
Причина: Добавлено сообщение
Я так понял, что в описанном алгоритме шифрации/дешифрации подразумевается 16-байтный ключ. Но сервер присылает нам только 4 байта.
Где брать остальные 12 байтов?
Добавлено через 1 час 0 минут
Вроде понял. Вроде взял не то описание.
нашел такое (8-байтный ключ. младшие 4 байта получаем от сервера, старшие как я понял фиксированные $87546CA1 (или их еще предварительно вычислить нужно?)):
Код:
char key_sc[8];
char key_cs[8];
void Encrypt(char *raw, int size)
{
int temp = 0;
for (int i=0; i<size; i++)
{
int temp2 = raw[i] &0xff;
raw[i] = (char)(temp2 ^ (key_cs[i&7] &0xff) ^ temp);
temp = raw[i];
}
int old = key_cs[0] &0xff;
old |= key_cs[1] << 8 &0xff00;
old |= key_cs[2] << 0x10 &0xff0000;
old |= key_cs[3] << 0x18 &0xff000000;
old += size;
key_cs[0] = (char)(old &0xff);
key_cs[1] = (char)(old >> 0x08 &0xff);
key_cs[2] = (char)(old >> 0x10 &0xff);
key_cs[3] = (char)(old >> 0x18 &0xff);
}
С учетом вышеприведенного, я перевел это на Дельфи так:
Код:
TXorKeyData=packed array[1..8] of byte;
type TXorKey=packed record
case boolean of
true: (KeyArray:TXorKeyData;);
false: (First_Key:cardinal;
SecondKey:cardinal;);
end;
...
procedure XOREncrypt(var data;len:integer;var key:TXorKey);
var
i:integer;
S:Pchar;
temp,temp2:char;
old:Cardinal;
begin
S:=Pchar(@data);
temp:=Char(0);
for i:=0 to len-1 do
begin
temp2:=S[i];
s[i]:=char(ord(temp2) xor key.KeyArray[i and 7] xor ord(temp));
temp:=s[i];
end;
key.First_Key:=Key.First_Key+len;
end;
Правильно? Или я что-то недопонял в сишной реализации алгоритма?
Последний раз редактировалось glukmaker, 14.10.2011 в 16:25.
Причина: Добавлено сообщение
Мой модуль для удобной работы с L2-потоком: http://pastebin.com/X9BnJJJ8
Не надо думать о шифровании, о делении потока на пакеты и прочих мелочах.
Требуется установить свои обработчики PacketEvent (сюда передается очередной дешифрованный пакет) и SendEvent (сюда передается строка для передачи на сервер).
Сырые данные от сервера передавать в метод ProcessData, отправлять через метод Send.
Обработчик PacketEvent получает объект класса TL2Packet (доступны все функции ReadX) и управляющий объект класса TL2Stream. Писать данные можно в свой объект TL2Packet (все WriteX функции), а потом вызываеть L2Stream.Send(L2Packet.Data).
Последний раз редактировалось Hint, 15.10.2011 в 13:58.
Вобщем у меня все получилось. Загвоздка была в том, что при выборе чара я слал его Id, а нужно было номер чарслота (как оказалось с в xor-шифровании я не сделал ошибки, как думал ранее).
Авторизацию (до посылки пакета EnterWorld включительно) реализовал.
И далее теперь могу принимать и отправлять пакеты.
Спасибо всем, кто помог!
Цитата:
Сообщение от Hint
Мой модуль для удобной работы с L2-потоком
Обязательно посмотрю. Я сам уже было подумал все, что я написал оформить в виде компонента. Но вот увидел твое сообщение. Эх. если бы ты раньше написал, я бы не стал мучаться... А то теперь не знаю, что взять за основу: твой модуль или то, что я уже сам написал дорабатывать.