Example #1
0
 /**
  * Creates new connection to OTServ administration backend.
  * 
  * <p>
  * This method automaticly handles RSA and XTEA encryption if such method is required by server including keys negotiations.
  * </p>
  * 
  * <p>
  * After connecting you should check {@link OTS_Admin::requiresLogin() if server requires login}.
  * </p>
  * 
  * @version 0.1.2
  * @since 0.1.2
  * @param string $host Target server.
  * @param int $port Port (7171 by default).
  * @throws E_OTS_ErrorCode When receive failed respond or unexpected message.
  * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream.
  */
 public function __construct($host, $port = 7171)
 {
     // saves connection sessint
     $this->host = $host;
     $this->port = $port;
     // opens connection
     $this->socket = fsockopen($this->host, $this->port);
     // 254 = OTAdmin protocol identifier
     $message = new OTS_Buffer(chr(254));
     // sends initial packet
     $respond = $this->send($message);
     $message->reset();
     $byte = $respond->getChar();
     // checks if it's HELLO packet
     if ($byte != self::RESPOND_HELLO) {
         throw new E_OTS_ErrorCode($byte);
     }
     // skips respond signature and protocol version
     $respond->getLong();
     $respond->getString();
     // saves protocol settings
     $this->policy = $respond->getShort();
     $this->options = $respond->getLong();
     // handles encryption initialisation if required
     if ($this->requiresEncryption() && $this->usesRSA1024XTEA()) {
         // requests public key
         $message->putChar(self::REQUEST_KEY_EXCHANGE);
         $message->putChar(self::ENCRYPTION_RSA1024XTEA);
         $respond = $this->send($message);
         $message->reset();
         $byte = $respond->getChar();
         // checks if it succeded
         if ($byte != self::RESPOND_KEY_EXCHANGE_OK) {
             throw new E_OTS_ErrorCode($byte, $respond->getString());
         }
         // we support only RSA 1024bit encryption for XTEA key sending
         if ($respond->getChar() != self::ENCRYPTION_RSA1024XTEA) {
             throw new E_OTS_ErrorCode($byte);
         }
         // reads binary form of public key (128 bytes)
         $key = OTS_BinaryTools::bin2Int(strrev($respond->getString(128)));
         // creates RSA cipher
         // as we have ready N computer here and we don't compute it by ourselves we can use a little hack, to save N as P * Q we will use P = N and Q = 1
         $rsa = new OTS_RSA($key, '1');
         $key = '';
         // generates random XTEA key
         for ($i = 0; $i < 4; $i++) {
             $key .= pack('L', rand(0, 4294967295));
         }
         $xtea = new OTS_XTEA($key);
         // sends XTEA key
         $message->putChar(self::REQUEST_ENCRYPTION);
         $message->putChar(self::ENCRYPTION_RSA1024XTEA);
         $message->putString($rsa->encrypt(chr(0) . $key), false);
         // we can't bind cipher yet since only respnd will be XTEA encrypted
         $respond = new OTS_Buffer($xtea->decrypt($this->send($message)->getBuffer()));
         $byte = $respond->getChar();
         // checks if encryption negotation succeeded
         if ($byte != self::RESPOND_ENCRYPTION_OK) {
             throw new E_OTS_ErrorCode($byte, $respond->getString());
         }
         // saves encryption/decryption cipher
         $this->cipher = $xtea;
     }
 }
Example #2
0
 /**
  * Ecnrypts message with RSA algorithm.
  * 
  * @version 0.1.2
  * @since 0.1.2
  * @param string $message Message to be encrypted.
  * @return string Encrypted message.
  */
 public function encrypt($message)
 {
     // chunk length
     $length = ceil($this->length / 8);
     // c = m^e mod n
     return str_pad(strrev(OTS_BinaryTools::int2Bin(bcpowmod(OTS_BinaryTools::bin2Int(strrev(str_pad($message, $length, chr(0)))), $this->e, $this->n))), $length, chr(0), STR_PAD_LEFT);
 }
Example #3
0
 /**
  * Decrypt XTEA-encrypted string.
  * 
  * @param string $message Encrypted message.
  * @return string Decrypted string.
  */
 public function decrypt($message)
 {
     // convert data to long
     $message = array_values(unpack('V*', $message));
     $length = count($message);
     // converts to unsigned integers
     foreach ($message as $index => $result) {
         if ($result < 0) {
             $message[$index] += 0xffffffff + 1;
         }
     }
     // decrypt the long data with the key
     $result = '';
     for ($i = 0; $i < $length; $i++) {
         $sum = 0xc6ef3720;
         $delta = 0x61c88647;
         $y = $message[$i];
         $z = $message[++$i];
         for ($j = 0; $j < 32; $j++) {
             $z = OTS_BinaryTools::unsignedAdd($z, -(OTS_BinaryTools::unsignedAdd($y << 4 ^ OTS_BinaryTools::unsignedRightShift($y, 5), $y) ^ OTS_BinaryTools::unsignedAdd($sum, $this->key[OTS_BinaryTools::unsignedRightShift($sum, 11) & 3])));
             $sum = OTS_BinaryTools::unsignedAdd($sum, $delta);
             $y = OTS_BinaryTools::unsignedAdd($y, -(OTS_BinaryTools::unsignedAdd($z << 4 ^ OTS_BinaryTools::unsignedRightShift($z, 5), $z) ^ OTS_BinaryTools::unsignedAdd($sum, $this->key[$sum & 3])));
         }
         // append the deciphered longs to the result data
         $result .= pack('VV', $y, $z);
     }
     // reads message length
     $offset = unpack('v', $result);
     return substr($result, 2, $offset[1]);
 }