shaman |
Дата: Четверг, 30.09.2010. Сообщение # 1
|
Заблокированный
Сообщений: 887
Нет на сайте
|
lock2key для hublist'а, Код для работы с хаблистом
Итак, по порядку. Известно что хаблисты используют схему $Lock-$Key. Основная проблема заключаеться в том, что этот алгоритм чуть-чуть отличается от обычного. Если быть точным, ровно на первый байт.
В интернете видел информацию, что большинство хаблистов благополучно игнорируют правильность этого кода и есть там один, особо задиристый. Однако, чем черт не шутит. Поэтому наваял свою реализацию на PHP.
Но, буду последователен. Исходником послужил код из исходников PtokaX хаба:
Code
uint16_t lport = (uint16_t)ntohs(addr.sin_port);
char cMagic = (char) ((lport&0xFF)+((lport>>8)&0xFF));
// strip the Lock data
char *temp;
if((temp = strchr(sBuffer+6, ' ')) != NULL) {
temp[0] = '\0';
}
// Compute the key
memcpy(sMsg, "$Key ", 5);
sMsg[5] = '\0';
size_t iLen = temp-sBuffer;
char v;
// first make the crypting stuff
for(size_t i = 6; i < iLen; i++) {
if(i == 6) {
v = sBuffer[i] ^ sBuffer[iLen] ^ sBuffer[iLen-1] ^ cMagic;
} else {
v = sBuffer[i] ^ sBuffer[i-1];
}
// Swap nibbles (0xF0 = 11110000, 0x0F = 00001111)
v = (char)(((v << 4) & 0xF0) | ((v >> 4) & 0x0F));
switch(v) {
case 0:
strcat(sMsg, "/%DCN000%/");
break;
case 5:
strcat(sMsg, "/%DCN005%/");
break;
case 36:
strcat(sMsg, "/%DCN036%/");
break;
case 96:
strcat(sMsg, "/%DCN096%/");
break;
case 124:
strcat(sMsg, "/%DCN124%/");
break;
case 126:
strcat(sMsg, "/%DCN126%/");
break;
default:
strncat(sMsg, (char *)&v, 1);
break;
}
}
На старте задается lport как локальный порт хаба, в подключении к хаблисту. У хаблиста порт, естественно, 2501. У нас же, тот что назначит система, а значит случайный.
sBuffer - содержит исходный $Lock код. sMsg - по завершении будет содержать нужный $Key код.
Теперь собственно код на PHP:
Code
function lock2key($_LOCK, $port)
{
$lockLength = strlen($_LOCK);
$LockToKey = '';
for ($j = 0; $j < strlen($_LOCK); $j++)
{
if($j == 0) {
$h = ord($_LOCK{0}) ^ 0 ^ ord( $_LOCK{ $lockLength - 1} ) ^ ($port % 256 + ($port>>8) % 256);
}
else {
$h = ord($_LOCK{$j}) ^ ord($_LOCK{$j-1});
}
$h = $h % 256;
$a = (($h<<4) & 240) | (($h>>4) & 15);
if($a == '126' or $a == '124' or $a == '96' or $a == '36' or $a == '5' or $a == '0') {
$LockToKey .= "/%DCN";
if ($a < 100) $LockToKey .= "0";
if ($a < 10) $LockToKey .= "0";
$LockToKey .= $a;
$LockToKey .= "%/";
}
else {
$LockToKey .= chr($a);
}
}
return $LockToKey;
}
Из заметных отличий от стандартного следующие:
Code
$h = ord($_LOCK{0}) ^ 0 ^ ord( $_LOCK{ $lockLength - 1} ) ^ ($port % 256 + ($port>>8) % 256);
Используется связка первого символа с нулем (вместо последнего символа), а затем с последним символом (вместо предпоследнего). Также, вместо константы 5, используется магический байт вычисляемый как сумма верхнего и нижнего байта шестнадцетиричного представления номера порта.
Все остальные "отличия" - экономия "на спичках" + изменения форматирования, не меняющие алгоритма работы.
Функция принимает два параметра, строку $Lock и номер порта.
Было бы неплохо этот код обосновать в соответствующей теме, описания протокола.
|
|
|
|