Что нового

Клиент - серверная защита вашего ПО.

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Могилу себе рою. Но ввиду участившихся вопросов про защиту своего ПО в формате "клиент - сервер", выкладываю саааааааамую первую версию своего сервера авторизации 2-х годичной давности. Кривую, банальную но работающую, с комментами
Часть 1
Код:
<?php
include('myrsa.class.php');
$MyRSA = new RSA();
//$MyServer = new Server();
//$Key = $MyServer->GenerateNewServerKeys();
//echo "1=".$Key["E"]."
2=".$Key["D"]."
3=".$Key["N"];
//exit;
//$date = new DateTime('2000-01-01');

/*  Алгоритм авторизации - начало описания
	Список запросов обрабатываемых сервером:
	1) Инициализация сессии					:	10000000 - 25000000
	1) Регистрация							:	25000001 - 35000000
	2) Авторизация							:	35000001 - 50000000
	3) Разрешение на действие				:	50000001 - 75000000
	4) Сохранение полученной статистики		:	75000001 - 99999999
	
	реализовано 1) Авторизация начинается с запроса клиентом открытых ключей сервера.
		реализовано 1.1) Клиент генерирует свои ключи, свой временный 8 значный ID и код запроса "Инициализации сессии"
		реализовано 1.2) По средством $_GET запроса клиент передает серверу 32 значное число в которое записаны $request.$tempID.$key[0].$key[2] данные клиента. 
			$request = Random(10000000, 25000000, 1)
			$key[0] = E $key[2] = N и это открытые ключи
			$tempID - сгенерированное функцией Random(20000000,99999999,1) случайное число которое используется только 
				на промежуточном этапе авторизации при первичном обмене ключами
		реализовано 2) Сервер принимает 24 значное число и раскладывает его на составляющие
		реализовано 2.1) Первые 8 знаков числа это $tempID, знаки с 9 под 16 это $key[0] = E клиента, знаки с 17 по 24 это $key[2] = N клиента.
		реализовано 2.2) Сервер имеет 3 значения: $tempID, $key[0], $key[2] клиента
		реализовано 2.3) Сервер генерирует свои E D N ключи командой generate_keys
		реализовано 2.4) Сервер заносит в SQLite бд запись, в поле Login вносится полученное от клиента $tempID и сгенерированные сервером для этого клиента D и N ключи в поля DKey и NKey соответственно
				после записи строка должна будет выглядеть так:
				Login	|Password	|Signature |DKey				|NKey
				$tempID	 null		 null		$Key[1] сервера		 $key[2] сервера
		реализовано 2.5) Сервер кодирует функцией Encrypt(text,e,n) свои открытые ключи, открытыми ключами клиента, 
				где $text = $key[0].$key[2] сервера, $e и $n = $key[0] и $key[2] клиента полученные в пункте 2.2 данного алгоритма
		реализовано 2.6) По средством Echo сервер отображает клиенту зашифрованное сообщение
	3) Клиент получает ответ на свой запрос отправленный в пункте 1.2
		реализовано 3.1) Полученное от сервера сообщение расшифровывается функцией Decrypt(text, d, n)
				где $text - полученный от сервера ответ
				$d и $n = key[1] и key[2] = закрытая пара ключей сгенерированная клиентом в пункте 1.1
		реализовано 3.2) Результатом функции Decrypt будут e и n = $key[0] и $key[2] открытые ключи сервера
		реализовано 3.3) клиент генерирует для себя новые ключи
				Полученными от сервера ключами клиент кодирует сообщение формата $tempID.$key[0].$key[2]|login|password|signature
				и отправляет его на сервер по средством $_GET запроса.
	4) Сервер получает сообщение длинною > 24 знаков
		4.1) Сервер последовательно считывает первые 3 группы чисел по 8 знаков и сохраняет в отдельную переменную всё что идет после них.
				первая группа (0-8) это $tempID клиента, вторая группа (8-16) это новое $e клиента, третья группа (16-24) это новое $n клиента
				$message - все оставшееся что идет после первых 3-х групп (тоесть зашифрованное клиентом сообщение для сервера
		4.2) Чтобы расшифровать полученное сообщение, серверу нужны занесенные в пункте 2.4 в базу D и N ключи. Сервер делает запрос в базу о наличии там записи у которой параметр Login будет 
				равен полученному в пункте 4.1 $tempID клиента
		4.3) Если сервер не нашел такую запись в базе => авторизация не верная, процесс прекращается.
				Если сервер нашел в базе запись с таким $tempID, он считывает записанные туда ключи
				результат: у сервера есть D и N ключи для расшифровке полученного в пункте 4.1 сообщения
		4.4) Сервер расшифровывает с помощью функции Decrypt() и полученных в пункте 4.3 D и N ключей, полученное в пункте 4.1 сообщение
				результатом будет Login, Password и Signature присланные клиентом после того как пользователь ввел их в него.
		4.5) Сервер ищет в базе совпадения Login и Password, если совпадение найдено сервер проверяет полученную от клиента Signature с той что хранится в базе
				Если Signature совпали то авторизация пройдена
				Если Signature = 0 сервер возвращает сообщение о необходимости сперва зарегистрироваться
				Если Signature не совпали, сервер возвращает сообщение о том что данная пара логина и пароля уже привязаны к другому компьютеру
				
				
	Алгоритм авторизации - конец описания*/
	
/* Регулярные выражения:
	Регулярка для распознования запроса:
	Reg*12345678\87657421[[email protected]/12aZ]0BEA0E07-F78F-8968-C9BD-92BCC7178AD5
	"/^([0-9]{5,8})(?:[\\\])([0-9]{5,8})(?:[\[])([a-zA-Z0-9]+[@][a-zA-Z0-9]+[.][a-zA-Z0-9]{1,5})(?:[\/])([a-zA-Z0-9]{4,12})(?:[\]])([A-Z0-9-]{30,45})$/"

	Регулярка для определения типа запроса Reg; Log; Stat; Sit
	Sit*12345678\87657421[[email protected]/12aZ]0BEA0E07-F78F-8968-C9BD-92BCC7178AD5
	/^(Reg|Log|Stat|Sit)[\*]([\S]+)$/
	
*/
$host="localhost:xxxx"; // у большинства хостеров этот параметр именно такой
$user="uxxxx_eveauth"; //ваше имя для подключения к MySQL
$pass="xxxxxx"; // Ваш пароль для подключения к MySQL
$bd_name="uxxxxx_eveauth"; // Имя создаваемой базы данных
$table_name="test_bd1"; // Имя создаваемой таблицы  
$filename = "DebugLog.txt"; //Лог файл для отладки сервера
$handle = fopen($filename, 'a'); //Открываем файл для записи с режимом "в конец файла"
$LastLogin = date("d-m-Y G:i:s", time()); //Текущее время обращения клиентом на сервер

$db = mysql_connect($host, $user, $pass) // Соединение с MySQL
   or die (mysql_error());
  
mysql_select_db ($bd_name, $db) // Выбор базы данных
   or die (mysql_error());

$var = "CREATE TABLE IF NOT EXISTS `users` (`Id` INT(15) UNIQUE, `Login` VARCHAR(35) UNIQUE, `Password` TEXT, `Signature` VARCHAR(45) UNIQUE, `tempIDforClient` INT(10) UNIQUE, `tempIDforServer` INT(10) UNIQUE, `EKey` TEXT, `DKey` TEXT, `NKey` TEXT, `Registered` TEXT, `LastLogin` TEXT, `WorkUntil` TEXT) "; //Создаем таблицу если не создана, поля ID, Login - уникальны
mysql_query ($var) // Отсылаем запрос на создание таблицы
  or die (mysql_error());
 
include('dateadd.php');
include('datediff.php');
/*
  $var = "INSERT INTO `users` (`id`, `Login`, `Password`, `Signature`, `DKey`, `NKey`) VALUES ('1234', 12, 34, 56, 78, 90)";
	mysql_query ($var); // Отсылаем запрос на создание таблицы
 $var = mysql_error();
 echo "qwqwqwq $var"; 
 */

//Обрабатываем результаты полученные от клиента
if ($_GET["eu"] == "") {










	//Получая пустое сообщение, мы готовимся передать клиенту данные необходимые ему для авторизации.
		//Ниже мы будем формировать глобальный указатель (поинтер)
	//Указатель формируется из нескольких случайных чисел и переменных $Pointer1, $Pointer2, $Pointer3
	//Длинна глобального указателя = 8 знаков
	//$Pointer1 <> $Pointer2 <> $Pointer3
	//Все поинтеры должны быть > 2
	//Первая цифра указателя, будет указывать клиенту на первую группу чисел в цепочке
	
	//Последующие поинтеры нам уже придется генерировать в цикле

	Do {
		$Pointer1 = rand(2,9); //Первый поинтер это любое случайное целое число от 2 до 9, будет указывать на tempID клиента
		$Pointer2 = rand(2,9); //Второй поинтер это любое случайное число от 2 до 9, будет указывать на E сервера
		$Pointer3 = rand(2,9); //Третий поинтер это любое случайное число от 2 до 9, будет указывать на N сервера
		if ($Pointer1<>$Pointer2 and $Pointer1<>$Pointer3 and $Pointer2<>$Pointer3) {//Все 3 числа уникальны, не повторяют другдруга
			break; //Прерываем цикл
		}
	} 
	While (1==1);
	//echo $Pointer1." ".$Pointer2." ".$Pointer3."
";
	//xTxxExxN
	$GlobalPointer = rand(1,9).$Pointer1.rand(10,99).$Pointer2.rand(10,99).$Pointer3; //Формируем Глобальный поинтер, который содержит в себе 3 других поинтера.
	Do {
		$RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
		$var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
	} While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
	$ServerEKey = $RSAkey[0]; //Присваиваем результаты генерации ключей к соответствующим переменным
	$ServerDKey = $RSAkey[1];
	$ServerNKey = $RSAkey[2];
	//Генерируем tempID для клиента и для сервера
	//tempID нужен для того, чтобы пройдя инициализацию соединения и получив его, при авторизации клиент передал его обратно серверу, и тот нашел в MySQL базе сохраненные для этого клиента D и N ключи и смогт расшифровать полученную от него информацию.
	$tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
	$tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа
	
	//То же самое действие нужно будет совершить и клиенту, при передаче tempIDforClient обратно на сервер. Это дделается для того, чтобы визуально было невозможно отследить зависимость получаемых и отправляемых данных
	
	//echo $tempIDforClient."
";
	//echo $tempIDforServer."
";
	//echo $GlobalPointer."
";
	
	//echo "
Pos ".$Pointer1." ID=".$tempID."
Pos ".$Pointer2." E=".$ServerEKey."
Pos ".$Pointer3." N=".$ServerNKey;
	$AuthPack = $GlobalPointer;
	for ($i = 2; $i <= rand(17,20); $i++) {
		if ($i == $Pointer1) {
			$AuthPack = $AuthPack."+".$tempIDforClient;
		}elseif ($i==$Pointer2) {
			$AuthPack = $AuthPack."+".$ServerEKey;
		}elseif ($i==$Pointer3) {
			$AuthPack = $AuthPack."+".$ServerNKey;
		}else {
			$AuthPack = $AuthPack."+".rand(1000000,99999999);
		}
		//echo $AuthPack."
";
	}
	$var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `tempIDforClient`, `tempIDforServer`, `EKey`, `DKey`, `NKey`, `LastLogin`) VALUES ('".$tempIDforServer."', '', '".$tempIDforServer."', '".$tempIDforClient."', '".$tempIDforServer."', '".$ServerEKey."', '".$ServerDKey."', '".$ServerNKey."', '".$LastLogin."')"; //Заносим tempIDfS, tempIDfC, E, D, N и LastLogin в базу данных, для последующей авторизации
	if (mysql_query ($var)) {// Отсылаем запрос на запись в таблицу
		echo $AuthPack; //Выводим клиенту сообщение с данными об авторизации
	}else{
		//Убрать отчет об ошибке
		$var = mysql_error();
		echo $var;
		exit;
	}
}else{ //Если запрос был не пустым
	$rMessage = str_replace(" ", "+", $_GET["eu"]); //заменяем пробелы в полученном сообщении на плюсы (просто лень было в РСА модуль лезть и заменять плюсы на пробелы там :)
    //Запрос артефакт, в результате шифровки с помощью РСА в запросе появился "-" О_о $rMessage = "10403764+28676114+9768264+17591956+24488473+40072948+57910146+22818710+20314213+39081874+45372827+59602846+22818710+12912249+31425026+25795662+39081874+31425026+45372827+40072948+39081874+25795662+7158421+20314213+51424582+51424582+51424582+51424582+51424582+51424582+51424582+20314213+31425026+57910146+22818710+-45114319+17591956+52628087+12024245+43048758+43261435+20314213+31425026+57910146+22818710+11069746+51805049+9768264+52628087+14406032+20314213+51424582+51424582+51424582+51424582+51424582+51424582+51424582+20314213+31425026+57910146+22818710+28266707+51424582+16710202+48865675+55635624+51424582+48865675+51424582+22818710+48505640+55835380+22818710+45372827+55835380+48505640+45372827+25795662+40072948+45372827+48505640+19034074+25795662+16710202+6027074+48505640+25795662+57910146+16710202+19034074+19034074+22818710+20314213+22818710+45372827+55635624+6027074+59602846+20314213+31425026+57910146+22818710";
	if(!preg_match("/^[0-9+-]+$/", $rMessage)) { //Если обнаружено что-либо отличное от цифр и плюсов. Иногда почему-то сам RSA кодирует и выдает отрицательное значение на какой-нибудь рандомный символ, нипонятная хуйня, добавлю проверку минусов в скрипт
		echo "Access denied Dont match regexp ^[0-9+-]+".$rMessage; //Отказываем клиенту в обработке его запроса
		exit;
	}
    //Тупро продолжаем работу если входящее значение нормальное
	$tempIDforServer = explode("+", $rMessage);//Разбиваем полученное сообщение знаком +, в [0] ячейке будет переданный нам от клиента передано tempIDforServer, по которому в MySQL мы сможем найти сгенеренные для него ранее E D N ключи и расшифровать полученное сообщение.
	$tempIDforServer = $tempIDforServer[0]; //Присваиваем переменной tempIDforServer только что полученный от клиента ID
	$rMessage = substr($rMessage,StrLen($tempIDforServer)+1); //Удаляем его из полученного сообщения, тем самым получая строку которую нам и надо будет расшифровать.
	$result = "SELECT * FROM `users` WHERE `tempIDforServer` = '".$tempIDforServer."'"; //Извлекаем из таблицы данные касаемо полученного только что ID
	$result = mysql_query ($result); // Отсылаем запрос на чтение из таблицы
	if ($result) { //В случае успеха
		$result = mysql_fetch_array($result); //Записываем полученные из таблицы данные в массив
		$dbLogin = $result['Login']; //Записываем данные хранимые в ассоциативном массиве, в соответствующие переменные
        $dbServerEKey = $result['EKey'];
		$dbServerDKey = $result['DKey'];
		$dbServerNKey = $result['NKey'];
        $dbtempIDforServer = $result['tempIDforServer'];
       // echo "Login = ".$tempID." ".$tIDfS;
        //exit;
		if (preg_match("/^.*(".$dbServerEKey."|".$dbServerNKey.").*$/", $rMessage, $out_arr)) {
            if ($dbLogin == "" or $dbtempIDforServer == "") {
                echo "Wrong Request";
                exit;
            }
			//Данный IF необходим для того случая, когда ранее сервер не смог расшифровать сообщение от клиента и вернул ему "Wrong Request".
			//Получив "Wrong Request" или же самостоятельно приняв решение о необходимости обновления ключей, клиент отправит на сервер свой текущий tempIDforServer и E или N ключи сервера, привязанные к этому tempIDforServer.
			//Увидев в полученном сообщение один из своих ключей, высланных этому tempID ранее, сервер поймет что клиент запрашивает новые ключи и tempIDforClient
			//Генерируем новые EDN сервера
            Do {
				$RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
				$var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
			} While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
			$ServerEKey = $RSAkey[0]; //Присваиваем результаты генерации ключей к соответствующим переменным
			$ServerDKey = $RSAkey[1];
			$ServerNKey = $RSAkey[2];
            //Генерируем для клиента новый tempIDforClient
            $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
            //Высчитываем из него новый tempIDforServer
            $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа
			//В зависимости от того в на какую запись были запрошены новые ключи, временную, Login = tIDfS или же постоянную (зарегистрированный логин), логин соответствует шаблону и <> tIDfS.
            //Удаляем временную запись с Login = tIDfS только что полученными от сервера из таблицы. Она нам уже не нужна, ниже будет создана новая запись.
            //Или же просто обновляем ключи для уже существующей записи

            //Ниже идущий запрос, не вызовет ошибки в случае если логина = $tempIDforServer в базе не найдено и если найдено - удалит временную запись
            $var = "DELETE FROM `users` WHERE `Login`='".$dbtempIDforServer."'";
            If (mysql_query ($var)) {
                //echo "tIDfS found in Login";
            }else{
                //Убрать отчет об ошибке
                $var = mysql_error();
                echo $var;
                exit;
            }

            //Исходя из учетки на которую был произведен запрос новых ключей, формируем MySQL запрос
            if ($dbLogin == $dbtempIDforServer and $dbLogin <> "") {
                //echo "Zaprosheni novie klu4i dlja vremennogo soedinenija";
                $var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `tempIDforClient`, `tempIDforServer`, `EKey`, `DKey`, `NKey`, `LastLogin`) VALUES ('".$tempIDforServer."', '', '".$tempIDforServer."', '".$tempIDforClient."', '".$tempIDforServer."', '".$ServerEKey."', '".$ServerDKey."', '".$ServerNKey."', '".$LastLogin."')"; //Заносим tempIDfS, tempIDfC, E, D, N и LastLogin в базу данных, для последующей авторизации
            }elseif ($dbLogin <> $dbtempIDforServer and $dbLogin <> "") {
                //echo "Zaprosheni novie klu4i dlja sushestvujushego logina 
 dblogin = ".$dbLogin."
 dbtIDfS =".$dbtempIDforServer."
";
                $var = "UPDATE `users` SET `tempIDforClient` = '".$tempIDforClient."', `tempIDforServer` = '".$tempIDforServer."', `EKey` = '".$ServerEKey."', `DKey` = '".$ServerDKey."', `NKey` = '".$ServerNKey."', `LastLogin` = '".$LastLogin."' WHERE `tempIDforServer`='".$dbtempIDforServer."'";
                //echo "
UPDATE `users` SET `tempIDforClient` = '".$tempIDforClient."', `tempIDforServer` = '".$tempIDforServer."', `EKey` = '".$ServerEKey."', `DKey` = '".$ServerDKey."', `NKey` = '".$ServerNKey."', `LastLogin` = '".$LastLogin."' WHERE `tempIDforServer`='".$dbtempIDforServer."'";
            }


            if (mysql_query ($var)) {// Отсылаем запрос на запись в таблицу
				//В будущем в генерацию нового ID и ключей нужно будет добавить рандомизацию, как при первичной авторизации
				$AuthPack = $tempIDforClient."+".$ServerEKey."+".$ServerNKey; //В данных об авторизации будет содержаться новый IDклиента, E и N сервера.
				echo $AuthPack; //Выводим клиенту сообщение с данными об авторизации
				exit;
			}else{
				//Убрать отчет об ошибке
				$var = mysql_error();
				echo $var;
				exit;
			}
			exit;
		}
	}else{
		$var = mysql_error(); //Тут надо будет заменить отчет об ошибке простым Access Denied
		echo $var;
		echo "Access denied";
		exit;
	}
	

	$DecMessage = $MyRSA->Decrypt($rMessage, $dbServerDKey, $dbServerNKey); //После того как полученное сообщение прошло все проверки, и мы убедились что в нем нету запроса новых ключей и ключи для этого clientID есть в базе, мы расшифровываем это сообщение
	if (!preg_match("/^(Reg|Log|Stat|Sit)[\*]([\S]+)$/", $DecMessage, $out_arr)) { //После расшифровки мы смотрим, какой запрос к нам пришел, на регистрацию, логин, сохранение статистики или же распознование ситуации
		echo "Wrong Request"; //Если же мы не смогли понять что за запрос к нам пришел, значит запрос был битый, пишем клиенту "Wong Request", что принудит его к запросу у сервера новых ключей
		//echo $DecMessage; //удалить
		exit;
	}

	$RequestType = $out_arr[1]; //Записываем в переменную $RequestType, тип запроса, регистрация, логин, сохранение статистики или же распознование ситуации (Reg|Log|Stat|Sit)
    $rMessage = $out_arr[2]; //В переменную $RegisterMessage записываем оставшуюся часть первоначального запроса, после того как отделили от неё тэг Reg

    if ($RequestType == "Reg") {//Если пришел запрос на регистрацию
                            if (!preg_match("/^([0-9]{5,8})(?:[\|])([0-9]{5,8})(?:[\[])([a-zA-Z0-9]+[@][a-zA-Z0-9]+[.][a-zA-Z0-9]{1,5})(?:[\+])([a-zA-Z0-9]{4,12})(?:[\]])([A-Z0-9-]{30,45})$/", $rMessage, $RegInfo)) {
                                /*С помощью регэкспа проверяем правильность формата запроса, он должен соответствовать шаблону:
                                16457557|71748221[[email protected]+1188]0BEA0E07-F78F-8968-C9BD-92BCC7178AD5
                                E		|N		 [Логин				  +Пароль]Сигнатура
                                08.06.2013 - Регэксп надо подредактировать сделав более гибким
                                */
                                echo "Wrong Reg Request";//Если полученный запрос не соответствует шаблону (например сообщение битое), оповещаем клиент о неправильности шаблона P.S. Это оповещение не инициализирует запрос клиентом новых ключей, а просто поставит его перед фактом, после чего он должен будет выдать пользователю сообщение о неповзможности регистрации
                                //echo "Wrong Request"; //Инициализировать перезапрос клиентом ключей
                                //echo $rMessage;
                                //echo $DecMessage; //удалить
                                exit;
                            }
                            //Если же всё ОК, выполняем необходимые действия для регистрации пользователя
                            //Такие как проверка уникальности логина и сигнатуры и в случае успеха, удаления временных данных и занесения полученных постоянных данных в базу
                            $clientEKey = $RegInfo[1];
                            $clientNKey = $RegInfo[2];
                            $clientLogin = $RegInfo[3];
                            $clientPassword = $RegInfo[4];
                            $clientSignature = $RegInfo[5];
                            //Удаляем из базы запись со временным ID и прочей хуетой, она нам больше никогда не понадобится т.к. она каждый раз новая
                            $var = "DELETE FROM `users` WHERE `Login`='".$tempIDforServer."'";
                            mysql_query ($var);

                            //Проверяем наличие в базе заправшиваемого логина
                            $result = "SELECT * FROM `users` WHERE `Login`='".$clientLogin."'"; //Смотрим есть ли в базе запрашиваемый логин
                            $result = mysql_query ($result);// Отправляем запрос в базу
                            if ($result) {  //Если он прошел
                                $result = mysql_fetch_array($result); //Потрошим результат
                                $dbLogin = $result['Login']; //Записываем полученные из таблицы данные, в соответствующие переменные
                                if ($dbLogin == $clientLogin ) { //Если логин был найден в базе
                                    Echo "Login [".$clientLogin."] is already registered"; //Оповещаем клиент об этом.
                                    exit;
                                }

                            }else{
                                $var = mysql_error();
                                echo $var;
                                exit;
                            }

                            //Если логина в базе нету, смотрим есть ли в базе Сигнатура регистрируемого компьютера
                            $result = "SELECT * FROM `users` WHERE `Signature`='".$clientSignature."'"; //Смотрим есть ли в базе запрашиваемая сигнатура
                            $result = mysql_query ($result);// Отправляем запрос в базу
                            if ($result) {
                                $result = mysql_fetch_array($result); //Потрошим результат
                                $dbSignature = $result['Signature']; //Записываем полученные из таблицы данные, в соответствующие переменные
                                if ($dbSignature == $clientSignature) { //Если сигнатура была найдена в базе
                                    echo "This computer is already assigned to another Login"; //Оповещаем об этом безобразии клиент
                                    exit;
                                }
                            }else{
                                $var = mysql_error();
                                echo $var;
                                exit;
                            }

                            //Если ни логин ни сигнатура не зарегистрированы в базе, регистрируем их

                            $Registered = $LastLogin; //Присваиваем время регистрации равное последнему логину
                                $temp_elements = explode(' ', $Registered); //Разбиваем текущую дату на "дату" и "время"
                                $date_elements = explode('-', $temp_elements[0]); //разбиваем "дату" на день, месяц, год
                                $time_elements = explode(':', $temp_elements[1]); //разбиваем "время" на часы и минуты
                                $timestamp = mktime($time_elements[0], $time_elements[1], $time_elements[2], $date_elements[1], $date_elements[0], $date_elements[2]); //Преваращаем полученные данные о днях часах минутах и тд во времянную метку UNIX
                                $WorkUntil = DateAdd("h", 10, $timestamp); //Добавляем к этой метке 10 часов
                            //$WorkUntil = DateAdd("d", 30, $timestamp); //Добавляем к этой метке 30 дней
                            $WorkUntil = date("d-m-Y G:i:s", $WorkUntil); //Конвертируем времянную метку обратно в дату в формате d-m-Y G:i:s, и получаем время равное "текущему + добавленное"

                            //Так как в данном случае мы лишь регистрируем учётку, все поля кроме логина, пароля, сигнатуры, времени регистрации и даты окончания функционирования учетки, мы не заполняем
                            $var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `Registered`, `WorkUntil`) VALUES ('".$clientLogin."', '".$clientPassword."', '".$clientSignature."', '".$Registered."', '".$WorkUntil."')";
                            $result = mysql_query ($var); //Отправляем запрос
                            if ($result) { //В случае успеха
                                echo "Login [".$clientLogin."] registered successfully"; //Говорим клиенту что регистрация завершена
                            }else{
                                $var = mysql_error();
                                echo $var;
                                exit;
                            }
P.S. Ставим лайки, подписываемся (c) YouTube
 
Автор
Belfigor

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Часть 2
Код:
<?php	}elseif ($RequestType == "Log")        {
                            //Echo "Login Request Receaved";
                            if (!preg_match("/^([0-9]{5,8})(?:[\|])([0-9]{5,8})(?:[\[])([a-zA-Z0-9]+[@][a-zA-Z0-9]+[.][a-zA-Z0-9]{1,5})(?:[\+])([a-zA-Z0-9]{4,12})(?:[\]])([A-Z0-9-]{30,45})$/", $rMessage, $RegInfo)) {
                                /*С помощью регэкспа проверяем правильность формата запроса, он должен соответствовать шаблону:
                                16457557|71748221[[email protected]+1188]0BEA0E07-F78F-8968-C9BD-92BCC7178AD5
                                E		|N		 [Логин				  +Пароль]Сигнатура
                                08.06.2013 - Регэксп надо подредактировать сделав более гибким
                                */
                                echo "Wrong Log Request";//Если полученный запрос не соответствует шаблону (например сообщение битое), оповещаем клиент о неправильности шаблона P.S. Это оповещение не инициализирует запрос клиентом новых ключей, а просто поставит его перед фактом, после чего он должен будет выдать пользователю сообщение о неповзможности регистрации
                                //echo "Wrong Request"; //Инициализировать перезапрос клиентом ключей
                                //echo $DecMessage; //удалить
                                exit;
                            }
                            $clientEKey = $RegInfo[1];
                            $clientNKey = $RegInfo[2];
                            $clientLogin = $RegInfo[3];
                            $clientPassword = $RegInfo[4];
                            $clientSignature = $RegInfo[5];
                            //echo $clientEKey."
".$clientNKey."
".$clientLogin."
".$clientPassword."
".$clientSignature;
        //Удаляем из базы запись со временным ID и прочей хуетой, она нам больше никогда не понадобится т.к. она каждый раз новая
        $var = "DELETE FROM `users` WHERE `Login`='".$tempIDforServer."'";
        mysql_query ($var);

        //Проверяем наличие в базе заправшиваемого логина
        //SELECT * FROM `users` WHERE `Login` = '[email protected]' AND `Password` = 'us02140' AND `Signature` = 'B7BF5670-7AD2-E881-0A3A-7FA26FEC3AC6'
        $result = "SELECT * FROM `users` WHERE `Login` = '".$clientLogin."' AND `Password` = '".$clientPassword."' AND `Signature` = '".$clientSignature."'";
        //$result = "SELECT * FROM `users` WHERE `Login` = '".'[email protected]'."' AND `Password` = '".'us02140'."' AND `Signature` = '".'B7BF5670-7AD2-E881-0A3A-7FA26FEC3AC6'."'";
        $result = mysql_query ($result);// Отправляем запрос в базу
        if ($result) {  //Если он прошел
            $result = mysql_fetch_array($result); //Потрошим результат
            //Так как в случае успеха мы найдем в базе нужную нам учетку, далее нас интиресует лишь можно ли ей работать, поэтому помимо логина запрашиваем еще результат поля WorkUntil
            $dbLogin = $result['Login']; //Записываем полученные из таблицы данные, в соответствующие переменные
            $dbWorkUntil = $result['WorkUntil'];
            if ($dbLogin <> $clientLogin ) { //Если логин был найден в базе
                echo "Login or password is wrong or they are assigned to another computer";
                exit;
            }

            //Если запросив в базе запись по заданным логину, паролю и сигнатуре, мы получили результат, нам надо проверить не истекла ли подписка у юзера.


            $timestamp = time(); //Смотрим сколько клиенту осталось работать. Тут мы не присваиваем переменной timestamp значение переменной $LastLogin определяемой в сааамом верху скрипта как например при регистрации юзера, а пользуемся функцией time() т.к. это бы вызвало необходимость дополнительной конвертации $LastLogin в timestamp т.к. в ней дата хранится в формате дд-мм-гггг чч-мм-сс
            $temp_elements = explode(' ', $dbWorkUntil); //Разбиваем переменную $dbWorkUntil из строкового значения на отдельные переменные в которых будет храниться каждое значение строки.
            $date_elements = explode('-', $temp_elements[0]);
            $time_elements = explode(':', $temp_elements[1]);
            $dbWorkUntil = mktime($time_elements[0], $time_elements[1], $time_elements[2], $date_elements[1], $date_elements[0], $date_elements[2]); //Конвертируем данные полученные после разбиения $dbWorkUntil на составляющие, в формат UNIX timestamp и присваиваем полученное значение переменной $dbWorkUntil.
            $TimeToWork = DateDiff("h", $timestamp, $dbWorkUntil); //Вычисляем разницу между временем оканчания работы и текущем временем
            //echo "
Time To Wotk Left: ".$TimeToWork." Hours";
            //echo strftime('%d-%m-%Y %H:%M:%S',$test);
            //$cWorkUntil = DateAdd("h", 10, $timestamp);
            If ($TimeToWork < 0) { //Проверяем сколько оплаченного времени осталось у юзера, если меньше 0 то
                Echo "Subscription Expired"; //пшел нахуй
            }else{
                //Теперь, если по группе Логин+Пароль+Сигнатура юзер был найден в базе и мы проверили что у него осталось оплаченное рабочее время
                //Мы готовы к тому, чтобы вернуть клиенту разрешение на работу а так же новые ключики сервера + обновить его ласт логин тайм
                Do { //Инициируем процесс генерации ключей
                    $RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
                    $var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
                } While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
                $serverEKey = $RSAkey[0]; //Присваиваем результаты генерации ключей к соответствующим переменным
                $ServerDKey = $RSAkey[1];
                $ServerNKey = $RSAkey[2];
                //Генерируем tempID для клиента и для сервера
                //tempID нужен для того, чтобы пройдя инициализацию соединения и получив его, при авторизации клиент передал его обратно серверу, и тот нашел в MySQL базе сохраненные для этого клиента D и N ключи и смогт расшифровать полученную от него информацию.
                $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
                $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа
                Do  {
                    //UPDATE `users` SET `tempIDforClient` = '12345678', `tempIDforServer` = '321456987', `EKey` = '1111111', `DKey` = '2222222', `NKey` = '33333333', `LastLogin` = '159753' WHERE `Login`='[email protected]'
                    $result = "UPDATE `users` SET `tempIDforClient` = '".$tempIDforClient."', `tempIDforServer` = '".$tempIDforServer."', `EKey` = '".$serverEKey."', `DKey` = '".$ServerDKey."', `NKey` = '".$ServerNKey."', `LastLogin` = '".$LastLogin."' WHERE `Login`='".$dbLogin."'";
                    $result = mysql_query ($result);// Отправляем запрос в базу
                    if ($result) {
                        //echo "Obnovleno";
                        break;
                    }else{
                        //echo "Need to generate new ID 
".$tempIDforClient."
".$tempIDforServer ;
                        //Если один из ID которые мы пытались записать а базу, там уже есть, генерируем новые и пытаемся заново
                        $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
                        $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа
                    }

                }
                While (1==1) ; //Повторяем цикл до тех пор пока не получим и не запишем уникальный ID в базу
                $returnmessage = $MyRSA->Encrypt($tempIDforClient."[".$serverEKey."|".$ServerNKey."]"."You Can Work", $clientEKey, $clientNKey);//шифруем свой EN ключ полученным EN ключем клиента
                echo $returnmessage; //отображаем клиенту зашифрованный ответ
            }
        }else{
            $var = mysql_error();
            echo $var;
            exit;
        }

                            //Echo "Login Request Receaved 2";
    }elseif ($RequestType == "Stat") {
                            ECHO "Save statistics request";
    }elseif ($RequestType == "Sit") {
                            echo "Recognize situation request";
    }
}









exit;
if ("qwqwqw" == "qwwqwq") {
	$rMessage = $_GET["eu"];
	//echo $rMessage ."
";
	$request = substr($rMessage,0,8);
	$rMessage = substr($rMessage,8);
	//echo $request."
";
	//echo $rMessage;
	if ($request >= 10000000 and $request <= 25000000) {
		$request = "InitializeSession";
	}elseif ($request >= 25000001 and $request <= 35000000) {
		$request = "RegisterUser";
	}elseif ($request >= 35000001 and $request <= 50000000) {
		$request = "LoginUser";
	}elseif ($request >= 50000001 and $request <= 75000000) {
		$request = "RecognizeSituation";
	}elseif ($request >= 75000001 and $request <= 99999999) {
		$request = "SaveStatistics";
	}
	//echo $request."
";


	If ($request == "InitializeSession") {
		$tempID = substr($rMessage,0,8); //tempID клиента
		$e = substr($rMessage,8,-8); //E клиента
		$n = substr($rMessage,-8); //N клиента
		$key = $MyRSA->generate_keys(0); //Генерим EDN для сервера
		$var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `DKey`, `NKey`) VALUES ('".$tempID."', '0', '".$tempID."', '".$key[1]."', '".$key[2]."')"; //Вносим tempID и DN ключи сервера в базу чтобы при следующий авторизации узнать клиента по его tempID и расшифровать полученное сообщение своим DN ключем
		if (mysql_query ($var)) {// Отсылаем запрос на запись в таблицу
			//echo "Data saved";
			$returnmessage = $MyRSA->Encrypt($key[0].$key[2], $e, $n);//шифруем свой EN ключ полученным EN ключем клиента
			echo $returnmessage; //отображаем клиенту зашифрованный ответ
		}else{
			$var = mysql_error();
			echo $var;
			exit;
		}
	}ElseIf ($request == "RegisterUser") {
		//echo "Получен запрос на регистрацию";
		$tempID = substr($rMessage,0,8); //tempID клиента
		$e = substr($rMessage,8,8); //E клиента
		$n = substr($rMessage,16,8); //N клиента
		$recivedmessage = substr($rMessage,24);

		$result = "SELECT * FROM `users` WHERE `Login` = '".$tempID."'";
		$result = mysql_query ($result);
		if ($result) {// Отсылаем запрос на чтение из таблицы
			$result = mysql_fetch_array($result);
			$tempID	=	$result['Login']; //Записываем полученные из таблицы данные, в соответствующие переменные
			$d		=	$result['DKey'];
			$n		=	$result['NKey'];
		}else{
			$var = mysql_error();
			echo $var;
			exit;
		}
		//echo "d = $d
tempID = $tempID
n = $n
message = $recivedmessage
";
		$decmessage = $MyRSA->Decrypt($recivedmessage, $d, $n);
		$split = explode("|", $decmessage);
		$Login = $split[0];
		$Password = $split[1];
		$Signature = $split[2];
		//echo "Login = $Login
 Password = $Password
Signature = $Signature
";
		$var = "DELETE FROM `users` WHERE `Login`='".$tempID."'";
		mysql_query ($var);
		$result = "SELECT * FROM users WHERE Login='".$Login."'"; //Смотрим есть ли в базе запрашиваемый логин
		$result = mysql_query ($result);
		If ($result) {
			$result = mysql_fetch_array($result);
			$cLogin=$result['Login'];
			$cPassword = $result['Password'];
			$cSignature = $result['Signature'];
			//$cd = $result['DKey'];
			//$cn = $result['NKey'];
			//echo "cd=$cd
sig=$cSignature
pass=$cPassword
";
			if	($Login == $cLogin) { //Смотрим нет ли такого логина уже в базе
				echo "Login ".$Login." is not available"; //Если есть шлем на ***
				exit;
			}else{
				 //= gmdate("Y-m-d H:i:s");
				$timestamp = time();
				$RegisterDate = date("d-m-Y G:i:s", $timestamp); //Получаем текущую дату в формате ДД-ММ-ГГГГ ЧЧ:ММ:СС
				$temp_elements = explode(' ', $RegisterDate);
				$date_elements = explode('-', $temp_elements[0]);
				$time_elements = explode(':', $temp_elements[1]);
				$timestamp = mktime($time_elements[0], $time_elements[1], $time_elements[2], $date_elements[1], $date_elements[0], $date_elements[2]);
				$WorkUntil = DateAdd("h", 10, $timestamp);
				//$WorkUntil = DateAdd("d", 30, $timestamp);
				$WorkUntil = date("d-m-Y G:i:s", $WorkUntil);
				//echo strftime('%d-%m-%Y %H:%M:%S',$timestamp);
				$var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `DKey`, `NKey`, `Registered`, `LastLogin`, `WorkUntil`) VALUES ('".$Login."', '".$Password."', '".$Signature."', '".$key[1]."', '".$key[2]."', '".$RegisterDate."', '".$qwe."', '".$WorkUntil."')";
				//В данном случае мы лишь регистрируем учетку, после регистрации сессия прервется. Поэтому параметры $key[1] $key[2] тупо не заданы
				if (mysql_query ($var)) { //Если регистрация прошла успешно
					//echo $RegisterDate."
"; //
					//echo $WorkUntil."
";
					echo "Registration Compleate"; //Выводим сообщение о завершении регистрации
				} else { //Если же зарегистрироваться не удалось, то это могло быть только из-за одинаковой сигнатуры компьютера
					//echo "Register Error";
					//exit;
					$var = mysql_error();
					if ($var == "Duplicate entry '".$Signature."' for key 'Signature'") {
						echo "Your computer is allready assigned for another Login"; //Выводим уведомление об этом
						exit;
					}
			echo $var;
			exit;
				}
			}
		}else{
			$var = mysql_error();
			echo $var;
			exit;
		}

		//echo "result=".$result."
";
	}ElseIf ($request == "LoginUser") {
		$tempID = substr($rMessage,0,8); //tempID клиента
		$new_cE = substr($rMessage,8,8); //E клиента. Этими ключами будет шифроваться отправляемый клиенту результат
		$new_cN = substr($rMessage,16,8); //N клиента.
		$recivedmessage = substr($rMessage,24);
		//echo $tempID."
".$e."<>".$n."<>";
		$result = "SELECT * FROM `users` WHERE `Login` = '".$tempID."'";
		$result = mysql_query ($result);// Отсылаем запрос на чтение из таблицы
		if ($result) {// Если успешно
			$result = mysql_fetch_array($result);
			$tempID	= $result['Login']; //Записываем полученные из таблицы данные, в соответствующие переменные
			$old_sD	= $result['DKey']; //D сервера. 		Получаем хранящиеся в таблице D и N ключи, необходимые для расшифровывания
			$old_sN	= $result['NKey']; //N сервера. 		только что полученного от клиента сообщения
		}else{
			$var = mysql_error();
			echo $var;
			exit;
		}
		//echo "d = $d
tempID = $tempID
n = $n
message = $recivedmessage
";
		$decmessage = $MyRSA->Decrypt($recivedmessage, $old_sD, $old_sN); //Расшифровываем полученное сообщение с помощью старых DN (закрытой пары) ключей
		$split = explode("|", $decmessage); //Разиваем его начасти получая логин пароль и сигнатуру
		$Login = $split[0];
		$Password = $split[1];
		$Signature = $split[2];
		//echo "Login = $Login
 Password = $Password
Signature = $Signature
";
		$var = "DELETE FROM `users` WHERE `Login`='".$tempID."'"; //Удаляем из таблицы users запись с логином tempID
		mysql_query ($var);
		$result = "SELECT * FROM users WHERE Login='".$Login."'"; //Смотрим есть ли в базе запрашиваемый логин
		$result = mysql_query ($result);
		If ($result) { //Если полученный от клиента логин найден в базе
			$result = mysql_fetch_array($result); //Выдергиваем из этой записи
			$cLogin=$result['Login']; //Логин
			$cPassword = $result['Password']; //Пароль
			$cSignature = $result['Signature']; //Сигнатуру
			//$cd = $result['DKey']; //Ключи
			//$cn = $result['NKey']; //d и n
			$cWorkUntil = $result['WorkUntil']; //и отметку о том до какого срока клиенту разрешается работать
			//echo "cd=$cd
sig=$cSignature
pass=$cPassword
work=$cWorkUntil
";
			If ($Password == $cPassword) { //Проверяем соответствует ли пароль из базы, паролю полученному от клиента
				If ($Signature == $cSignature) { //Если соответствует, смотрим соответствует ли сигнатура из базы, полученной от клиента
					//echo "test1
";
					$timestamp = time(); //Смотрим сколько клиенту осталось работать
					$temp_elements = explode(' ', $cWorkUntil);
					$date_elements = explode('-', $temp_elements[0]);
					$time_elements = explode(':', $temp_elements[1]);
					$cWorkUntil = mktime($time_elements[0], $time_elements[1], $time_elements[2], $date_elements[1], $date_elements[0], $date_elements[2]);
					$TimeToWork = DateDiff("h", $timestamp, $cWorkUntil); //Вычисляем разницу между временем оканчания работы и текущем временем
					//echo "
Time To Wotk Left: ".$TimeToWork." Hours";
					//echo strftime('%d-%m-%Y %H:%M:%S',$test);
					//$cWorkUntil = DateAdd("h", 10, $timestamp);
					If ($TimeToWork < 0)	{ //Если у него еще есть рабочее время
						Echo "Subscription Expired";
					} else {
						//echo "Succes Login Start 
";
						//	Тут надо вернуть
						//	1) Рразрешение на работу
						//	2) Новые ключи сервера
						//	3) Записать в базу время последнего логина


						//$tempID = substr($rMessage,0,8); //tempID клиента
						//$e = substr($rMessage,8,-8); //E клиента
						//$n = substr($rMessage,-8); //N клиента
						$LastLogin = date("d-m-Y G:i:s", time());
						$key = $MyRSA->generate_keys(0); //Генерим EDN для сервера
						//$var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `DKey`, `NKey`) VALUES ('".$cLogin."', '0', '".$tempID."', '".$key[1]."', '".$key[2]."')"; //Вносим tempID и DN ключи сервера в базу чтобы при следующий авторизации узнать клиента по его tempID и расшифровать полученное сообщение своим DN ключем
						//$var = "INSERT INTO `users` (`Login`, `Password`, `Signature`, `DKey`, `NKey`, `Registered`, `LastLogin`, `WorkUntil`) VALUES ('".$Login."', '".$Password."', '".$Signature."', '".$key[1]."', '".$key[2]."', '".$RegisterDate."', '".$qwe."', '".$WorkUntil."')";
						//$var = "UPDATE `users` SET `LastLogin`='".$LastLogin."', `DKey`='".$key[1]."', `NKey`='".$key[2]."' WHERE `Login`='".$cLogin."')";
						$var = "UPDATE `users` SET `LastLogin` = '".$LastLogin."', `DKey` = '".$key[1]."', `NKey`='".$key[2]."' WHERE `Login`='".$cLogin."'";
						//UPDATE `users` SET `LastLogin` = "test3", `DKey` = "123", `NKey`="234" WHERE `Login`="upchk"
						if (mysql_query ($var)) {// Отсылаем запрос на запись в таблицу
							//Теперь генирируем случайный 8 значный уникальный ID, который мы вернем клиенту для последующей идентификации
								$test = rand(10000000,99999999); //Генерим число
								Do {
									$var = "UPDATE `users` SET `Id` = '".$test."' WHERE `Login`='".$cLogin."'"; //Пытаемся засунуть его в базу
									if (mysql_query ($var)) {//Если всё прошло успешно, ID оказался уникальным
										break; //Прерываем цикл
									}else{ //В противном случае
										$test = rand(10000000,99999999); //Генерим новый случайный уникальный ID
									}
								}
								While (1==1) ; //Повторяем цикл до тех пор пока не получим и не запишем уникальный ID в базу

							$returnmessage = $MyRSA->Encrypt($key[0].$key[2].$test, $new_cE, $new_cN);//шифруем свой EN ключ полученным EN ключем клиента
							echo $returnmessage; //отображаем клиенту зашифрованный ответ
						}else{
							$var = mysql_error();
							echo $var;
							exit;
						}
						//Echo "You can work:".$TimeToWork;
					}
				} else {
					echo "This computer is allready assigned to another user";
					exit;
				}
			} else {
				echo "Wrong Login or Password";
				exit;
			}
		}
		//echo "
Login Finished
";
	}ElseIf ($request == "RecognizeSituation") {
		fwrite($handle, "==============================>start record RECOGNIZE SITUATION\n");
		$ID = substr($rMessage,0,8); //tempID клиента
		$new_cE = substr($rMessage,8,8); //E клиента. Этими ключами будет шифроваться отправляемый клиенту результат
		$new_cN = substr($rMessage,16,8); //N клиента.
		$recivedmessage = substr($rMessage,24);
		//echo $ID."
".$new_cE."
".$new_cN."
".$recivedmessage."
";
		fwrite($handle, "Client temp ID = ".$ID."\n Client new cE = ".$new_cE."\n Client new cN = ".$new_cN."\n Client message = ".$recivedmessage."\n");
		//exit;
		$result = "SELECT * FROM `users` WHERE `Id` = '".$ID."'";
		$result = mysql_query ($result);// Отсылаем запрос на чтение из таблицы
		if ($result) {// Если успешно
			$result = mysql_fetch_array($result);
			$cLogin=$result['Login']; //Логин
			$cPassword = $result['Password']; //Пароль
			$cSignature = $result['Signature']; //Сигнатурf
			$old_sD	= $result['DKey']; //D сервера. 		Получаем хранящиеся в таблице D и N ключи, необходимые для расшифровывания
			$old_sN	= $result['NKey']; //N сервера. 		только что полученного от клиента сообщения
			$cWorkUntil = $result['WorkUntil']; //и отметку о том до какого срока клиенту разрешается работать

			//echo $recivedmessage."
";
			//echo "TEST END";
			$decmessage = $MyRSA->Decrypt($recivedmessage, $old_sD, $old_sN); //Расшифровываем полученное сообщение с помощью старых DN (закрытой пары) ключей
			//echo $decmessage;
			fwrite($handle, $decmessage."\n"); //Записываем расшифрованную ситуацию в лог
			//exit;
			$split = explode("|", $decmessage); //Разиваем его начасти получая логин пароль и сигнатуру
			$Signature = $split[0];
			$Situation1 = $split[1];
			if ($Situation1 >= 1 and $Situation1 <= 3) {
				$Situation1 = "Docked";
			}elseif ($Situation1 >= 4 and $Situation1 <= 6) {
				$Situation1 = "InWarp";
			}elseif ($Situation1 >= 7 and $Situation1 <= 9) {
				$Situation1 = "InSpace";
			}
			//echo $Situation1."
";
			$Situation2 = $split[2];
			if ($Situation2 >= 1 and $Situation2 <= 2) {
				$Situation2 = "Full";
			}elseif ($Situation2 >= 8 and $Situation2 <= 9) {
				$Situation2 = "Empty";
			}elseif ($Situation2 >= 3 and $Situation2 <= 7) {
				$Situation2 = "Not Empty";
			}
			//echo $Situation2."
";
			$Situation3 = $split[3];
			if ($Situation3 >= 1 and $Situation3 <= 2) {
				$Situation3 = "InAutoSpace";
			}elseif ($Situation3 >= 3 and $Situation3 <= 7) {
				$Situation3 = "InBelt";
			}elseif ($Situation3 >= 8 and $Situation3 <= 9) {
				$Situation3 = "#";
			}
			//echo $Situation3."
";
			$Situation4 = $split[4];
			if ($Situation4 >= 1 and $Situation4 <= 2) {
				$Situation4 = "Target Selected";
			}elseif ($Situation4 >= 3 and $Situation4 <= 4) {
				$Situation4 = "Target Locked AND Selected";
			}elseif ($Situation4 >= 5 and $Situation4 <= 6) {
				$Situation4 = "No Target Selected";
			}elseif ($Situation4 >= 7 and $Situation4 <= 8) {
				$Situation4 = "Target Locked NOT Selected";
			}elseif ($Situation4 == 9) {
				$Situation4 = "#";
			}
			//echo $Situation4."
";



			$LogicState = $Situation1."|".$Situation2."|".$Situation3."|".$Situation4;
			//echo $LogicState."
";
			fwrite($handle, "Situation = ".$LogicState."\n");
			If ($LogicState == "Docked|Not Empty|#|#" Or
					$LogicState == "Docked|Full|#|#") {
				$LogicState = "Unload Cargo";
			}elseif ($LogicState == "Docked|Empty|#|#") {
				$LogicState = "Undock";
			}elseif ($LogicState == "InSpace|Empty|InAutoSpace|#") {
				$LogicState = "Warp Belt";
			}elseif ($LogicState == "InWarp|#|#|#") {
				$LogicState = "Wait";
			}elseif ($LogicState == "InSpace|Empty|InBelt|No Target Selected" Or
					$LogicState == "InSpace|Empty|InBelt|Target Locked NOT Selected" Or
					$LogicState == "InSpace|Not Empty|InBelt|No Target Selected" Or
					$LogicState == "InSpace|Not Empty|InBelt|Target Locked NOT Selected") {
				$LogicState = "Select Target";
			}elseif ($LogicState == "InSpace|Empty|InBelt|Target Selected" Or
					$LogicState == "InSpace|Not Empty|InBelt|Target Selected") {
				$LogicState = "Lock Target";
			}elseif ($LogicState == "InSpace|Empty|InBelt|Target Locked AND Selected" Or
					$LogicState == "InSpace|Not Empty|InBelt|Target Locked AND Selected") {
				$LogicState = "Launch Strips";
			}elseif ($LogicState == "InSpace|Not Empty|InAutoSpace|#" Or
					$LogicState = "InSpace|Full|#|#") {
				$LogicState = "Dock Station";
			}else{
				$LogicState = "Error";
			}
			//echo $Signature."
".$LogicState;
			fwrite($handle, "Recognized = ".$LogicState."\n");

			$LastLogin = date("d-m-Y G:i:s", time());
			$key = $MyRSA->generate_keys(0); //Генерим EDN для сервера
			$var = "UPDATE `users` SET `LastLogin` = '".$LastLogin."', `DKey` = '".$key[1]."', `NKey`='".$key[2]."' WHERE `Login`='".$cLogin."'";
			if (mysql_query ($var)) {//Если всё прошло успешно, ID оказался уникальным
			}else{
				echo "error
".$var;
			}
			$test = rand(10000000,99999999); //Генерим число
			Do {
				$var = "UPDATE `users` SET `Id` = '".$test."' WHERE `Login`='".$cLogin."'"; //Пытаемся засунуть его в базу
				if (mysql_query ($var)) {//Если всё прошло успешно, ID оказался уникальным
					break; //Прерываем цикл
				}else{ //В противном случае
					$test = rand(10000000,99999999); //Генерим новый случайный уникальный ID
				}
			}
			While (1==1) ; //Повторяем цикл до тех пор пока не получим и не запишем уникальный ID в базу

			$returnmessage = $MyRSA->Encrypt($key[0]."|".$key[2]."@".$test."*".$LogicState, $new_cE, $new_cN);//шифруем свой EN ключ полученным EN ключем клиента
			echo $returnmessage;
			//Echo "END LOGIC!!!";
			fwrite($handle, "Return to client: \n key[0] = ".$key[0]."\n key[2] = ".$key[2]."\n tempID = ".$test."\n Logic State = ".$LogicState." \n new cE = ".$new_cE."\n new cN = ".$new_cN);
			fwrite($handle, "\n Message to encrypt: \n".$key[0]."|".$key[2]."@".$test."*".$LogicState);
			fwrite($handle, "==============================>end of record RECOGNIZE SITUATION\n");
			fclose($handle);
		}else{
			$var = mysql_error();
			echo $var;
			exit;
		}

		//echo $request."
";
	}ElseIf ($request == "SaveStatistics") {
		echo $request."
";
	}
	//echo "
END
";
}

Class Server {
	Private $MyRSA; //Тут мы занимаемся какой-то непонятной но обязательной хуетой
	Public Function __construct() //И тут
	{
		$this->MyRSA=new RSA(); //И тут тоже
	}
	
	Public Function GenerateNewServerKeys() {
		Do { //Генерируем новые ключи
						//Запросы в другой класс стали ебанистической длинны
			$RSAkey = $this->MyRSA->generate_keys(0); //Генерим EDN для сервера
			$var = $this->MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
		} While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
		$ServerKey = Array("E"=>$RSAkey[0], "D"=>$RSAkey[1], "N"=>$RSAkey[2]);
		Return $ServerKey; //И вуаля, первая функция в собственном классе готова.
	}
}
?>
 
Автор
Belfigor

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941


Добавлено:
Сообщение автоматически объединено:

И небольшой апдейт описания алгоритма, выстраданный в процессе тестов первых версий:
Код:
Описание сервера:
1) Сервер должен быть да*уя портабильным. Перенос сервера на другой продукт, должен осуществляться лишь изменением имени сервера и комбинациями результатов
    "Вопрос - Ответ", для логической части клиента.
2) СЕРВЕР НЕ ДОЛЖЕН ПРОИЗВОДИТЬ РЕГИСТРАЦИЮ ПОЛЬЗОВАТЕЛЕЙ ЧЕРЕЗ КЛИЕНТСКИЙ ЗАПРОС
3) Вся регистрация пользователя на продукте обслуживаемом сервером происходит через сайт, путем нажатия кнопки "Активировать продукт", ну или мб как-то по другому она будет называться.
4) Функции сервера:
    4.1) Авторизация клиентской программы
    4.2) Сбор информации получаемой от клиентской программы
    4.3) Рассмотрение ситуаций присылаемых клиентской программой и возврат решения которое программа должна выполнить
    4.4) Блекджек и шлюхи, но в будущем.

Принцип работы:
    Инициализацию производит клиент, путем отправки пустого запроса, на что сервер отсылает результат содержищий в себе ключи шифрования и временный ID клиента по которому сервер в будущем его авторизует
    Всё последующее взаимодействие с клиентом происходит по устоявшемуся с помощью временных ID ключей соединению. На каждое новое соединение - новый временный ID.
    Логин и пароль передаются только в момент авторизации. Далнейшее соединение поддерживается временными ID. КАЖДЫЙ РАЗ НОВЫМИ, НА КАЖДЫЙ ЗАПРОС - НОВЫЙ ВЫСЕР ID.
    Никаких сессий и куков. (Вариант на рассмотрении).

Сервер может пользоваться функциями движка ботгейминга в случае необходимости. Так же сервер использует синхронизированный с клиентом алгоритм РСА.
И так и быть, первая версия этого сервера:
Код:
<?php 
TODO List:
    Организовать инициализацию сессии (тупо скопипиздить из предидущей версии сервера, там она вполне кошерна
    Организовать авторизацию
    Организовать распознавание ситуаций
    Организовать получения ключевых настроек клиента с сервера
    Организовать сбор статистики (второстепенно)
 */
define('CAN_WORK', '1'); //Для невозможности прямого доступа к другим используемым сервером скриптам, используем константу, без объявления которой скрипт тупо пошлет весь мир нахуй.
define('PRODUCT_NAME', 'eve-trade-chan'); //Имя продукта
define('USERS_TABLE', 'users'); //Имя таблицы пользователей
define('OPTIONS_TABLE', 'options'); //Имя таблицы настроек пользователя
define('INITIALIZATION_TABLE', "authserver_temp"); //Имя таблицы через которую происходит инициализация сессии
/*  Так как опции у различных программ, которые надо передать им, могут кординально отличаться, это наверное будет
    самый переписываемый модуль в сервере. Нужно подумать как упростить эту задачу :think:
 */
include_once $_SERVER['DOCUMENT_ROOT']."/include/config.php"; //Инклудим совместный с сайтом файл конфига где хранятся всякие константы например для доступа к БД
include_once ROOT_PATH."/include/engine.php"; //Подключаем файл движка
include('myrsa.class.php'); //Инклудим РСА класс
$MyRSA = new RSA(); //Объявляем РСА класс

//Все приготовления выполнены, теперь сервер может принимать инфу, подключаться к базе и пользоваться необходимыми ему функциями движка
//Подклчаемся к БД
$db = mysql_connect(DB_HOST, DB_USER, DB_PASS) // Соединение с MySQL, данные об авторизации хранятся в config.php
    or die (mysql_error()); //Вырезать отчет об ошибке, заменить какой нибудть текстовой ошибкой типа "Ведутся технические работы"

mysql_select_db (DB_NAME, $db) //Вырезать отчет об ошибке, заменить какой нибудть текстовой ошибкой типа "Ведутся технические работы"
    or die (mysql_error());
//Конец подключения к БД

//Начало самой логики сервера
if ($_GET["eu"] == "") {
    //Получая пустое сообщение, мы готовимся передать клиенту данные необходимые ему для авторизации.
    //Ниже мы будем формировать глобальный указатель (поинтер)
    //Указатель формируется из нескольких случайных чисел и переменных $Pointer1, $Pointer2, $Pointer3
    //Длинна глобального указателя = 8 знаков
    //$Pointer1 <> $Pointer2 <> $Pointer3
    //Все поинтеры должны быть > 2
    //Первая цифра указателя, будет указывать клиенту на первую группу чисел в цепочке

    //Последующие поинтеры нам уже придется генерировать в цикле

    Do {
        $Pointer1 = rand(2,9); //Первый поинтер это любое случайное целое число от 2 до 9, будет указывать на tempID клиента
        $Pointer2 = rand(2,9); //Второй поинтер это любое случайное число от 2 до 9, будет указывать на E сервера
        $Pointer3 = rand(2,9); //Третий поинтер это любое случайное число от 2 до 9, будет указывать на N сервера
        if ($Pointer1<>$Pointer2 and $Pointer1<>$Pointer3 and $Pointer2<>$Pointer3) {//Все 3 числа уникальны, не повторяют другдруга
            break; //Прерываем цикл
        }
    }
    While (1==1);
    //echo $Pointer1." ".$Pointer2." ".$Pointer3."
";
    //xTxxExxN
    $GlobalPointer = rand(1,9).$Pointer1.rand(10,99).$Pointer2.rand(10,99).$Pointer3; //Формируем Глобальный поинтер, который содержит в себе 3 других поинтера.
    Do {
        $RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
        $var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
    } While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
    $ServerEKey = $RSAkey[0]; //Присваиваем результаты генерации ключей к соответствующим переменным
    $ServerDKey = $RSAkey[1];
    $ServerNKey = $RSAkey[2];
    //Генерируем tempID для клиента и для сервера
    //tempID нужен для того, чтобы пройдя инициализацию соединения и получив его, при авторизации клиент передал его обратно серверу, и тот нашел в MySQL базе сохраненные для этого клиента D и N ключи и смогт расшифровать полученную от него информацию.
    $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
    $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа

    //То же самое действие нужно будет совершить и клиенту, при передаче tempIDforClient обратно на сервер. Это дделается для того, чтобы визуально было невозможно отследить зависимость получаемых и отправляемых данных

    //echo $tempIDforClient."
";
    //echo $tempIDforServer."
";
    //echo $GlobalPointer."
";

    //echo "
Pos ".$Pointer1." ID=".$tempID."
Pos ".$Pointer2." E=".$ServerEKey."
Pos ".$Pointer3." N=".$ServerNKey;
    $AuthPack = $GlobalPointer;
    for ($i = 2; $i <= rand(17,20); $i++) {
        if ($i == $Pointer1) {
            $AuthPack = $AuthPack."+".$tempIDforClient;
        }elseif ($i==$Pointer2) {
            $AuthPack = $AuthPack."+".$ServerEKey;
        }elseif ($i==$Pointer3) {
            $AuthPack = $AuthPack."+".$ServerNKey;
        }else {
            $AuthPack = $AuthPack."+".rand(1000000,99999999);
        }
        //echo $AuthPack."
";
    }
    $var = "INSERT INTO `".DB_PREFIX."_".INITIALIZATION_TABLE."` (`tempIDforClient`, `tempIDforServer`, `EKey`, `DKey`, `NKey`, `lastlogin`) VALUES ('".$tempIDforClient."', '".$tempIDforServer."', '".$ServerEKey."', '".$ServerDKey."', '".$ServerNKey."', '".time()."')"; //Заносим tempIDfS, tempIDfC, E, D, N и LastLogin в базу данных, для последующей авторизации
    //echo $var."
";
    if (mysql_query ($var)) {// Отсылаем запрос на запись в таблицу
        echo $AuthPack; //Выводим клиенту сообщение с данными об авторизации
    }else{
        //Убрать отчет об ошибке
        $var = mysql_error();
        echo $var;
        exit;
    }
}else{//Если запрос был не пустым
    $rMessage = str_replace(" ", "+", $_GET["eu"]); //заменяем пробелы в полученном сообщении на плюсы (просто лень было в РСА модуль лезть и заменять плюсы на пробелы там :)
    if(!preg_match("/^[0-9+-]+$/", $rMessage)) { //Если обнаружено что-либо отличное от цифр и плюсов. Иногда почему-то сам RSA кодирует и выдает отрицательное значение на какой-нибудь рандомный символ, нипонятная хуйня, добавлю проверку минусов в скрипт
        echo "Access denied Dont match regexp ^[0-9+-]+".$rMessage; //Отказываем клиенту в обработке его запроса
        exit;
    }
    //Тупро продолжаем работу если входящее значение нормальное



    //echo "rMessage = ".$rMessage."
";



    $tempIDforServer = explode("+", $rMessage);//Разбиваем полученное сообщение знаком +, в [0] ячейке будет переданный нам от клиента tempIDforServer, по которому в MySQL мы сможем найти сгенеренные для него ранее E D N ключи и расшифровать полученное сообщение.
    $tempIDforServer = $tempIDforServer[0]; //Присваиваем переменной tempIDforServer только что полученный от клиента ID
    $tempIDforServer = mysql_real_escape_string($tempIDforServer); //Прослешиваем полученную инфу
    $rMessage = substr($rMessage,StrLen($tempIDforServer)+1); //Удаляем его из полученного сообщения, тем самым получая строку которую нам и надо будет расшифровать.
    /*  Итак теперь мы имеем результат. tempIDforServer и rMessage. Для того чтобы нам расшифровать rMessage, нам надо по tempIDforServer
        найти в таблице EDN ключи сервера.
        Проблема следующая:
            У нас две таблицы.
            1) Таблица с логинами и паролями пользователей, где храняться EDN ключи уже инициализированных сессий. И дабы не засорять её лишними записми таблица 2)
            2) Таблица инициализации сессий. В неё постоянно при инициализации сессии, заносятся tempID и EDN ключи инициализационного пакета. И при последующем запросе логина, запись удаляется.
        Поэтому тут нам надо определиться, с какой таблицей мы будем работать дальше, с таблицей инициализации или же с таблицей уже установленных связей.
    */

    //Так как инициализация связи происходит реже чем запросы на поддержание связи, сначала нам надо отправить запрос в таблицу поддержания связи и узнать есть ли там полученный только что tempIDforServer.
    //echo "Надо найти tIDfS ".$tempIDforServer."
";
    //echo "SELECT * FROM `".DB_PREFIX."_".PRODUCT_NAME."_".USERS_TABLE."` WHERE `tempIDforServer` = '".$tempIDforServer."'
";
    //echo "Обращаюсь в таблицу инициализации
";


    //первый запрос отправляем в таблицию инициализации связи, дабы посмотреть нет ли там схожих tIDfS
    $connection_type = false;
    $result = "SELECT * FROM `".DB_PREFIX."_".INITIALIZATION_TABLE."` WHERE `tempIDforServer` = '".$tempIDforServer."'";
    $result = mysql_query ($result);//Отправляем запрос в БД
    if ($result) { //Если в процессе отправки запроса не возникло проблем
        $result = mysql_fetch_array ($result); //Потрошим результат
        if ($result['login']=='' and $result['tempIDforServer']<>''){ //Если логин пуст, а tIDfS нет
            //Значит запись найдена в таблице инициализации
            $connection_type = "Initialization";
        }else{ //Если результат не соответствует таблице инициализации
            //Отправляем запрос к таблице поддержки связи
            $result = "SELECT * FROM `".DB_PREFIX."_".PRODUCT_NAME."_".USERS_TABLE."` WHERE `tempIDforServer` = '".$tempIDforServer."'"; //Извлекаем из таблицы данные касаемо полученного только что ID
            $result = mysql_query ($result);//Отправляем запрос в MySQL
            if ($result) { //Если запрос прошел удачно
                $result = mysql_fetch_array ($result);//Потрошим результат
                if ($result['login']<>'' and $result['tempIDforServer']<>''){ //Если логин НЕ пуст и tIDfS не пуст.
                    //Значит запись найдена в таблице поддержки связи
                    $connection_type = "Post Initialization";
                }else{
                    //echo "Wrong Request";
                    //exit;
                }
            }else{
                echo "Connection error 2"; //Убрать в релизе
                exit;
            }
        }
    }else{
        echo "Connection error 1";//Убрать в релизе
        exit;
    }

    if (!$connection_type){
        echo "Wrong Request2";
        exit;
    }elseif ($connection_type=="Initialization") {
        $dbServerEKey = $result['EKey'];
        $dbServerDKey = $result['DKey'];
        $dbServerNKey = $result['NKey'];
        $dbtempIDforServer = $result['tempIDforServer'];
    }elseif ($connection_type=="Post Initialization") {
        $dbLogin = $result['login']; //Записываем данные хранимые в ассоциативном массиве, в соответствующие переменные
        $dbServerEKey = $result['EKey'];
        $dbServerDKey = $result['DKey'];
        $dbServerNKey = $result['NKey'];
        $dbtempIDforServer = $result['tempIDforServer'];
    }

    //echo "dbLogin =".$dbLogin."
";
    //echo "dbServerEKey =".$dbServerEKey."
";
    //echo "dbServerDKey =".$dbServerDKey."
";
    //echo "dbServerNKey =".$dbServerNKey."
";
    //echo "dbtempIDforServer =".$dbtempIDforServer."
";

    if (preg_match("/^.*(".$dbServerEKey."|".$dbServerNKey.").*$/", $rMessage, $out_arr)) { //проверяем есть ли в полученном запросе dbServerEKey или же dbServerNKey, значит мы получили SOS от клиента, он не смог расшифровать ответ
        if ($dbtempIDforServer == "") { //если dbtIDfS - пустой, значит возможно нас пытаются наебать.
            echo "Wrong Request1"; //Шлём в пизду
            exit;
        }
        //Данный IF необходим для того случая, когда ранее сервер не смог расшифровать сообщение от клиента и вернул ему "Wrong Request".
        //Получив "Wrong Request" или же самостоятельно приняв решение о необходимости обновления ключей, клиент отправит на сервер свой текущий tempIDforServer и E или N ключи сервера, привязанные к этому tempIDforServer.
        //Увидев в полученном сообщение один из своих ключей, высланных этому tempID ранее, сервер поймет что клиент запрашивает новые ключи и tempIDforClient
        //Генерируем новые EDN сервера

        //Повторяем момент инициализации сессии.
        Do {
            $RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
            $var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
        } While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.

        Do {
            $Pointer1 = rand(2,9); //Первый поинтер это любое случайное целое число от 2 до 9, будет указывать на tempID клиента
            $Pointer2 = rand(2,9); //Второй поинтер это любое случайное число от 2 до 9, будет указывать на E сервера
            $Pointer3 = rand(2,9); //Третий поинтер это любое случайное число от 2 до 9, будет указывать на N сервера
            if ($Pointer1<>$Pointer2 and $Pointer1<>$Pointer3 and $Pointer2<>$Pointer3) {//Все 3 числа уникальны, не повторяют другдруга
                break; //Прерываем цикл
            }
        }
        While (1==1);
        //echo $Pointer1." ".$Pointer2." ".$Pointer3."
";
        //xTxxExxN
        $GlobalPointer = rand(1,9).$Pointer1.rand(10,99).$Pointer2.rand(10,99).$Pointer3; //Формируем Глобальный поинтер, который содержит в себе 3 других поинтера.
        Do {
            $RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
            $var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
        } While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
        $ServerEKey = $RSAkey[0]; //Присваиваем результаты генерации ключей к соответствующим переменным
        $ServerDKey = $RSAkey[1];
        $ServerNKey = $RSAkey[2];
        //Генерируем tempID для клиента и для сервера
        //tempID нужен для того, чтобы пройдя инициализацию соединения и получив его, при авторизации клиент передал его обратно серверу, и тот нашел в MySQL базе сохраненные для этого клиента D и N ключи и смогт расшифровать полученную от него информацию.
        $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
        $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа

        //То же самое действие нужно будет совершить и клиенту, при передаче tempIDforClient обратно на сервер. Это дделается для того, чтобы визуально было невозможно отследить зависимость получаемых и отправляемых данных

        //echo $tempIDforClient."
";
        //echo $tempIDforServer."
";
        //echo $GlobalPointer."
";

        //echo "
Pos ".$Pointer1." ID=".$tempID."
Pos ".$Pointer2." E=".$ServerEKey."
Pos ".$Pointer3." N=".$ServerNKey;
        $AuthPack = $GlobalPointer;
        for ($i = 2; $i <= rand(17,20); $i++) {
            if ($i == $Pointer1) {
                $AuthPack = $AuthPack."+".$tempIDforClient;
            }elseif ($i==$Pointer2) {
                $AuthPack = $AuthPack."+".$ServerEKey;
            }elseif ($i==$Pointer3) {
                $AuthPack = $AuthPack."+".$ServerNKey;
            }else {
                $AuthPack = $AuthPack."+".rand(1000000,99999999);
            }
            //echo $AuthPack."
";
        }

        if ($connection_type=='Initialization') { //Если косяк случился в момент инициализации
            $var = "DELETE FROM `".DB_PREFIX."_".INITIALIZATION_TABLE."` WHERE `tempIDforServer`='".$dbtempIDforServer."'";
            If (mysql_query ($var)) {
                //echo "tIDfS found in Login";
            }else{
                //Убрать отчет об ошибке
                $var = mysql_error();
                echo $var;
                exit;
            }
        }

        //Исходя из запроса, формируем MySQL запрос
        if ($connection_type=='Initialization') {
            //echo "Zaprosheni novie klu4i dlja vremennogo soedinenija";
            $var = "INSERT INTO `".DB_PREFIX."_".INITIALIZATION_TABLE."` (`tempIDforClient`, `tempIDforServer`, `EKey`, `DKey`, `NKey`, `lastlogin`) VALUES ('".$tempIDforClient."', '".$tempIDforServer."', '".$ServerEKey."', '".$ServerDKey."', '".$ServerNKey."', '".time()."')"; //Заносим tempIDfS, tempIDfC, E, D, N и LastLogin в базу данных, для последующей авторизации
        }elseif ($connection_type=='Post Initialization') {
            //echo "Zaprosheni novie klu4i dlja sushestvujushego logina 
 dblogin = ".$dbLogin."
 dbtIDfS =".$dbtempIDforServer."
";
            $var = "UPDATE `".DB_PREFIX."_".PRODUCT_NAME."_".USERS_TABLE."` SET `tempIDforClient` = '".$tempIDforClient."', `tempIDforServer` = '".$tempIDforServer."', `EKey` = '".$ServerEKey."', `DKey` = '".$ServerDKey."', `NKey` = '".$ServerNKey."', `lastlogin` = '".time()."' WHERE `tempIDforServer`='".$dbtempIDforServer."'";
            //echo "
UPDATE `users` SET `tempIDforClient` = '".$tempIDforClient."', `tempIDforServer` = '".$tempIDforServer."', `EKey` = '".$ServerEKey."', `DKey` = '".$ServerDKey."', `NKey` = '".$ServerNKey."', `LastLogin` = '".$LastLogin."' WHERE `tempIDforServer`='".$dbtempIDforServer."'";
        }

        if (mysql_query ($var)) {// Отсылаем запрос на запись в таблицу
            //В будущем в генерацию нового ID и ключей нужно будет добавить рандомизацию, как при первичной авторизации
            //$AuthPack = $tempIDforClient."+".$ServerEKey."+".$ServerNKey; //В данных об авторизации будет содержаться новый IDклиента, E и N сервера.
            echo $AuthPack; //Выводим клиенту сообщение с данными об авторизации
            exit;
        }else{
            //Убрать отчет об ошибке
            $var = mysql_error();
            echo $var;
            exit;
        }
    }

    //Расшифровываем полученное сообщение
    $DecMessage = $MyRSA->Decrypt($rMessage, $dbServerDKey, $dbServerNKey); //После того как полученное сообщение прошло все проверки, и мы убедились что в нем нету запроса новых ключей и ключи для этого clientID есть в базе, мы расшифровываем это сообщение
    if (!preg_match("/^(Log|Stat|Sit)[\*]([\S]+)$/", $DecMessage, $out_arr)) { //После расшифровки мы смотрим, какой запрос к нам пришел, на регистрацию, логин, сохранение статистики или же распознование ситуации
        echo "Wrong Request"; //Если же мы не смогли понять что за запрос к нам пришел, значит запрос был битый, пишем клиенту "Wong Request", что принудит его к запросу у сервера новых ключей
        //echo $DecMessage; //удалить
        exit;
    }

    $RequestType = $out_arr[1]; //Записываем в переменную $RequestType, тип запроса, регистрация, логин, сохранение статистики или же распознование ситуации (Reg|Log|Stat|Sit)
    $rMessage = $out_arr[2]; //В переменную $RegisterMessage записываем оставшуюся часть первоначального запроса, после того как отделили от неё тэг Reg

    echo "Request Type: ".$RequestType."
";
    echo "rMessage: ".$rMessage. "
";

    if ($RequestType == "Log")        {
        Echo "Login Request Receaved
";
        if (!preg_match("/^([0-9]{5,8})(?:[\|])([0-9]{5,8})(?:[\[])([a-zA-Z0-9]{5,16})(?:[\+])([a-zA-Z0-9]{4,12})$/", $rMessage, $RegInfo)) {
            /*С помощью регэкспа проверяем правильность формата запроса, он должен соответствовать шаблону:
            16457557|71748221[[email protected]+1188]0BEA0E07-F78F-8968-C9BD-92BCC7178AD5
            E		|N		 [Логин				  +Пароль]Сигнатура
            08.06.2012 - Регэксп надо подредактировать сделав более гибким
            */
            echo "Wrong Log Request";//Если полученный запрос не соответствует шаблону (например сообщение битое), оповещаем клиент о неправильности шаблона P.S. Это оповещение не инициализирует запрос клиентом новых ключей, а просто поставит его перед фактом, после чего он должен будет выдать пользователю сообщение о неповзможности регистрации
            //echo "Wrong Request"; //Инициализировать перезапрос клиентом ключей
            //echo $DecMessage; //удалить
            exit;
        }
        $clientEKey = $RegInfo[1];
        $clientNKey = $RegInfo[2];
        $clientLogin = $RegInfo[3];
        $clientPassword = $RegInfo[4];
        $clientSignature = $RegInfo[5];
        echo $clientEKey."
".$clientNKey."
".$clientLogin."
".$clientPassword."
".$clientSignature;
        //Удаляем из базы запись со временным ID и прочей хуетой, она нам больше никогда не понадобится т.к. она каждый раз новая
        $var = "DELETE FROM `users` WHERE `Login`='".$tempIDforServer."'";
        mysql_query ($var);

        //Проверяем наличие в базе заправшиваемого логина
        //SELECT * FROM `users` WHERE `Login` = '[email protected]' AND `Password` = 'usxxxx0' AND `Signature` = 'B7BF5670-7AD2-E881-0A3A-7FA26FEC3AC6'
        $result = "SELECT * FROM `".DB_PREFIX."_".PRODUCT_NAME."_".USERS_TABLE."` WHERE `login` = '".$clientLogin."' AND `pass` = '".$clientPassword."'";
        //$result = "SELECT * FROM `users` WHERE `Login` = '".'[email protected]'."' AND `Password` = '".'xxxxxxx40'."' AND `Signature` = '".'B7BF5670-7AD2-E881-0A3A-7FA26FEC3AC6'."'";
        $result = mysql_query ($result);// Отправляем запрос в базу
        if ($result) {  //Если он прошел
            $result = mysql_fetch_array($result); //Потрошим результат
            //Так как в случае успеха мы найдем в базе нужную нам учетку, далее нас интиресует лишь можно ли ей работать, поэтому помимо логина запрашиваем еще результат поля WorkUntil
            $dbLogin = $result['login']; //Записываем полученные из таблицы данные, в соответствующие переменные
            $dbWorkUntil = $result['workuntil'];
            if ($dbLogin <> $clientLogin ) { //Если логин был найден в базе
                echo "Login or password is wrong or they are assigned to another computer";
                exit;
            }
            echo "Login: :".$dbLogin."
 WorkUntil: ".$dbWorkUntil."
";
            //Если запросив в базе запись по заданным логину, паролю и сигнатуре, мы получили результат, нам надо проверить не истекла ли подписка у юзера.


            $timestamp = time(); //Смотрим сколько клиенту осталось работать. Тут мы не присваиваем переменной timestamp значение переменной $LastLogin определяемой в сааамом верху скрипта как например при регистрации юзера, а пользуемся функцией time() т.к. это бы вызвало необходимость дополнительной конвертации $LastLogin в timestamp т.к. в ней дата хранится в формате дд-мм-гггг чч-мм-сс
            $temp_elements = explode(' ', $dbWorkUntil); //Разбиваем переменную $dbWorkUntil из строкового значения на отдельные переменные в которых будет храниться каждое значение строки.
            $date_elements = explode('-', $temp_elements[0]);
            $time_elements = explode(':', $temp_elements[1]);
            $dbWorkUntil = mktime($time_elements[0], $time_elements[1], $time_elements[2], $date_elements[1], $date_elements[0], $date_elements[2]); //Конвертируем данные полученные после разбиения $dbWorkUntil на составляющие, в формат UNIX timestamp и присваиваем полученное значение переменной $dbWorkUntil.
            $TimeToWork = DateDiff("h", $timestamp, $dbWorkUntil); //Вычисляем разницу между временем оканчания работы и текущем временем
            //echo "
Time To Wotk Left: ".$TimeToWork." Hours";
            //echo strftime('%d-%m-%Y %H:%M:%S',$test);
            //$cWorkUntil = DateAdd("h", 10, $timestamp);
            If ($TimeToWork < 0) { //Проверяем сколько оплаченного времени осталось у юзера, если меньше 0 то
                Echo "Subscription Expired"; //пшел нахуй
            }else{
                //Теперь, если по группе Логин+Пароль+Сигнатура юзер был найден в базе и мы проверили что у него осталось оплаченное рабочее время
                //Мы готовы к тому, чтобы вернуть клиенту разрешение на работу а так же новые ключики сервера + обновить его ласт логин тайм
                Do { //Инициируем процесс генерации ключей
                    $RSAkey = $MyRSA->generate_keys(0); //Генерим EDN для сервера
                    $var = $MyRSA->TestKeys($RSAkey[0], $RSAkey[1], $RSAkey[2]); //Тестируем ключи на пригодность
                } While ($var == "Not Valid Keys") ;//До тех пор пока не получим рабочие пары. Как правило с первого раза.
                $serverEKey = $RSAkey[0]; //Присваиваем результаты генерации ключей к соответствующим переменным
                $ServerDKey = $RSAkey[1];
                $ServerNKey = $RSAkey[2];
                //Генерируем tempID для клиента и для сервера
                //tempID нужен для того, чтобы пройдя инициализацию соединения и получив его, при авторизации клиент передал его обратно серверу, и тот нашел в MySQL базе сохраненные для этого клиента D и N ключи и смогт расшифровать полученную от него информацию.
                $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
                $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа
                Do  {
                    //UPDATE `users` SET `tempIDforClient` = '12345678', `tempIDforServer` = '321456987', `EKey` = '1111111', `DKey` = '2222222', `NKey` = '33333333', `LastLogin` = '159753' WHERE `Login`='[email protected]'
                    $result = "UPDATE `users` SET `tempIDforClient` = '".$tempIDforClient."', `tempIDforServer` = '".$tempIDforServer."', `EKey` = '".$serverEKey."', `DKey` = '".$ServerDKey."', `NKey` = '".$ServerNKey."', `LastLogin` = '".$LastLogin."' WHERE `Login`='".$dbLogin."'";
                    $result = mysql_query ($result);// Отправляем запрос в базу
                    if ($result) {
                        //echo "Obnovleno";
                        break;
                    }else{
                        //echo "Need to generate new ID 
".$tempIDforClient."
".$tempIDforServer ;
                        //Если один из ID которые мы пытались записать а базу, там уже есть, генерируем новые и пытаемся заново
                        $tempIDforClient = rand(10000000,99999999);//tempID для клиента генерируется и передается в том виде в каком есть
                        $tempIDforServer = (int)substr($tempIDforClient*4,-8);//tempID клиента, который будет сохранён на сервере, надо умножить на какое-нибудь число (в данном случае 4) и взять последние 8 знаков этого числа
                    }

                }
                While (1==1) ; //Повторяем цикл до тех пор пока не получим и не запишем уникальный ID в базу
                $returnmessage = $MyRSA->Encrypt($tempIDforClient."[".$serverEKey."|".$ServerNKey."]"."You Can Work", $clientEKey, $clientNKey);//шифруем свой EN ключ полученным EN ключем клиента
                echo $returnmessage; //отображаем клиенту зашифрованный ответ
            }
        }else{
            $var = mysql_error();
            echo $var;
            exit;
        }

        //Echo "Login Request Receaved 2";
    }elseif ($RequestType == "Stat") {
        ECHO "Save statistics request";
    }elseif ($RequestType == "Sit") {
        echo "Recognize situation request";
    }

}
?>


Добавлено:
Сообщение автоматически объединено:

P.S. Память если мне не изменяет, вторая версия диаметрально отличается от первой, в плане реализации процесса авторизации.
 
Автор
Belfigor

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
а сами придумайте :smile:
 
Верх