blowfish encryption/decryption support

Back to PHP-IRC Feature Requests

Page: 1  
From User Message Body
IdanB
Post #654
Member
Date: 6:46 pm, Dec 6 2007
Posts: 2


hello,

tried to go over docs & modules on site, but i've not seen any mention of making blowfish crypt support.

specifically i'm only looking for support that will echo output encrypted & otherway around - something that will make it "transparent" for bot recieving triggers from encypted chan.

empty
Post #685
Member
Date: 6:19 pm, Feb 28 2008
Posts: 9


Haven't been able to implement blowfish so it becomes transparent, however I found a nice set of functions to encrypt/decrypt output/input.

Code

class ircBFish
  {
    // Conversion table
    var $B64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    function bytetoB64($ec)
    {
      $dc = "";

      $k = -1;
      while($k < (strlen($ec) - 1)) {

        $k++;
        $left = (ord($ec{$k}) << 24);
        $k++;
        $left += (ord($ec{$k}) << 16);
        $k++;
        $left += (ord($ec{$k}) << 8);
        $k++;
        $left += ord($ec{$k});

        $k++;
        $right = (ord($ec{$k}) << 24);
        $k++;
        $right += (ord($ec{$k}) << 16);
        $k++;
        $right += (ord($ec{$k}) << 8);
        $k++;
        $right += ord($ec{$k});

        for($i = 0; $i < 6; $i++) {
          $dc .= $this->B64{$right & 0x3F};
          $right = $right >> 6;
        }

        for($i = 0; $i < 6; $i++) {
          $dc .= $this->B64{$left & 0x3F};
          $left = $left >> 6;
        }

      }

      return $dc;
    }

    function B64tobyte($ec)
    {
      $dc = "";

      $k = -1;
      while($k < (strlen($ec) - 1)) {

        $right = 0;
        $left = 0;

        for($i = 0; $i < 6; $i++) {
          $k++;
          $right |= @strpos($this->B64, $ec{$k}) << ($i * 6);
        }

        for($i = 0; $i < 6; $i++) {
          $k++;
          $left |= @strpos($this->B64, $ec{$k}) << ($i * 6);
        }

        for($i = 0; $i < 4; $i++)
          $dc .= chr(($left & (0xFF << ((3 - $i) * 8))) >> ((3 - $i) * 8));

        for ($i = 0; $i < 4; $i++)
          $dc .= chr(($right & (0xFF << ((3 - $i) * 8))) >> ((3 - $i) * 8));

      }

      return $dc;
    }

    function encrypt($text, $key)
    {
      $td = mcrypt_module_open(MCRYPT_BLOWFISH, "", MCRYPT_MODE_ECB, "");
      $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);

      $text .= str_repeat(chr(0), 8 - (strlen($text) % 8));

      mcrypt_generic_init($td, $key, $iv);

      $ec = mcrypt_generic($td, $text);

      mcrypt_module_close($td);

      return $this->bytetoB64($ec);
    }

    function decrypt($text, $key)
    {
      $td = mcrypt_module_open(MCRYPT_BLOWFISH, "", MCRYPT_MODE_ECB, "");
      $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);

      mcrypt_generic_init($td, $key, $iv);

      $tmp = mdecrypt_generic($td, $this->B64tobyte($text));
      $tmp = str_replace(chr(0), "", $tmp);

      mcrypt_module_close($td);

      return $tmp;
    }


Then you could use a function triggered by RAW and a if ($line['to'] == $correct_channel) to decrypt the string.

empty
Post #700
Member
Date: 4:01 pm, Mar 15 2008
Posts: 9


Me and my merry band of friends was able to implement blowfish into the core making it transparent and fully functional with triggers, it may not be a nice implementation. But it works.

Added this right after the normal vars are declared in irc.php.

Code
var $B64 = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';


Changed the function readInput to decrypt.

Code
    private function readInput()
    {
        if ($this->status != STATUS_CONNECTED_REGISTERED && $this->status != STATUS_CONNECTED_SENTREGDATA)
        {
            return false;
        }

        if ($this->socketClass->isDead($this->sockInt) && !$this->socketClass->hasLine($this->sockInt))
        {
            $this->disconnect();
            $this->status = STATUS_ERROR;
            $this->exception = new ReadException("Failed while reading from socket");
            return false;
        }
        
        if ($this->socketClass->hasLine($this->sockInt))
        {
            $this->timeoutTimer = time();

            if ($this->lastPing == 1)
            {
                $this->lagTime = time() - $this->lastPingTime;
            }
            $this->lastPing = 0;

            $line = $this->socketClass->getQueueLine($this->sockInt);
            
            $this->stats['BYTESDOWN'] += strlen($line);

            $this->log($line);

            if (substr($line, 0, 1) != ":")
            {
                $line = ":Server " . $line;
            }

            $line = substr($line, 1);

            $parts = explode(chr(32), $line);


            if (isset($this->clientConfig['blowfish']) && $parts[1] == 'PRIVMSG' )
            {
                $line = str_replace('+OK ', '', $line);
            }


            $params = substr($line,    strlen($parts[0]) + strlen($parts[1]) +    strlen($parts[2]) + 3);
            if (strpos($params, " :"))
            {
                $params = substr($params, 0, strpos($params, " :"));
            }

            $offset1 = strpos($parts[0], '!');
            $offset2 = $offset1 + 1;
            $offset3 = strpos($parts[0], '@') + 1;
            $offset4 = $offset3 - $offset2 - 1;
            $offset5 = strpos($line, " :") + 2;

            unset($this->lVars);
            
            $linetext = substr($line, $offset5);
    
            if (isset($this->clientConfig['blowfish']) && $parts[1] == 'PRIVMSG')
            {

                if (!is_array($this->clientConfig['blowfish']) && $this->clientConfig['blowfish'] == $parts[2])
                {
                    $blowfishKey = $this->clientConfig['blowkey'];

                    $params = $this->blowDecrypt($params, $blowfishKey);
                    $linetext = $this->blowDecrypt($linetext, $blowfishKey);
                }
                else if (is_array($this->clientConfig['blowfish']) && in_array($parts[2], $this->clientConfig['blowfish']))
                {
                    $blowfishKeyIndex = array_search($parts[2], $this->clientConfig['blowfish']);
                    $blowfishKey = $this->clientConfig['blowkey'][$blowfishKeyIndex];

                    $params = $this->blowDecrypt($params, $blowfishKey);
                    $linetext = $this->blowDecrypt($linetext, $blowfishKey);
                }
                else
                {
                    return;
                }
            }


            $this->lVars = array(    'from'        =>     $parts[0],
                                    'fromNick'    =>    substr($parts[0], 0, $offset1),
                                    'fromIdent'    =>    substr($parts[0], $offset2, $offset4),
                                    'fromHost'    =>    substr($parts[0], $offset3),
                                    'cmd'        =>    $parts[1],
                                    'to'        =>    $parts[2],
                                    'text'        =>    $linetext,
                                    'params'    =>    trim($params),
                                    'raw'        =>    ":" . $line,
                                );
            

            if ($offset5 === false)
            {
                $line['text'] = "";
            }

            if (intval($this->lVars['cmd']) > 0)
            {
                $this->parseServerMsgs($this->lVars['cmd']);
            }
            else
            {
                $this->parseMsgs();
            }
            
            $this->parserClass->parseLine($this->lVars);
        }

        if ($this->socketClass->hasQueue($this->sockInt))
        {
            return true;
        }

        return false;
    }


Altered the privMsg function to encode output if blowfish has been specified in the bot.conf.

Code
    public function privMsg($who, $msg, $queue = 1)
    {
        if (isset($this->clientConfig['blowfish']))
        {

            if (!is_array($this->clientConfig['blowfish']) && $this->clientConfig['blowfish'] == $who)
            {
                $blowfishKey = $this->clientConfig['blowkey'];

                $msg = '+OK '.$this->blowCrypt($msg, $blowfishKey);
            }
            else if (is_array($this->clientConfig['blowfish']) && in_array($who, $this->clientConfig['blowfish']))
            {
                $blowfishKeyIndex = array_search($who, $this->clientConfig['blowfish']);
                $blowfishKey = $this->clientConfig['blowkey'][$blowfishKeyIndex];

                $msg = '+OK '.$this->blowCrypt($msg, $blowfishKey);
            }
        }

        $text = array(    'USER'    =>    $who,
                        'TEXT'    =>    'PRIVMSG ' . $who . ' :' .  $msg);

        if ($queue)
        {
            $this->pushAfter($text);
        }
        else
        {
            $this->pushBefore($text);
        }
    }


Added these 4 functions in the end of irc.php
Code
    public function blowCrypt($text, $key)
    {
        $td = mcrypt_module_open(MCRYPT_BLOWFISH, "", MCRYPT_MODE_ECB, "");
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);

        $text .= str_repeat(chr(0), 8 - (strlen($text) % 8));

        mcrypt_generic_init($td, $key, $iv);

        $ec = mcrypt_generic($td, $text);

        mcrypt_module_close($td);

        return $this->bytetoB64($ec);
    }

    public function blowDecrypt($text, $key)
    {
        $td = mcrypt_module_open(MCRYPT_BLOWFISH, "", MCRYPT_MODE_ECB, "");
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);

        mcrypt_generic_init($td, $key, $iv);

        $tmp = mdecrypt_generic($td, $this->B64tobyte($text));
        $tmp = str_replace(chr(0), "", $tmp);

        mcrypt_module_close($td);

        return $tmp;
    }
    public function bytetoB64($ec)
    {
        $dc = "";

        $k = -1;
        while($k < (strlen($ec) - 1)) {

            $k++;
            $left = (ord($ec{$k}) << 24);
            $k++;
            $left += (ord($ec{$k}) << 16);
            $k++;
            $left += (ord($ec{$k}) << 8);
            $k++;
            $left += ord($ec{$k});

            $k++;
            $right = (ord($ec{$k}) << 24);
            $k++;
            $right += (ord($ec{$k}) << 16);
            $k++;
            $right += (ord($ec{$k}) << 8);
            $k++;
            $right += ord($ec{$k});

            for($i = 0; $i < 6; $i++) {
                $dc .= $this->B64{$right & 0x3F};
                $right = $right >> 6;
            }

            for($i = 0; $i < 6; $i++) {
                $dc .= $this->B64{$left & 0x3F};
                $left = $left >> 6;
            }

        }

        return $dc;
    }

    public function B64tobyte($ec)
    {
        $dc = "";

        $k = -1;
        while($k < (strlen($ec) - 1)) {

            $right = 0;
            $left = 0;

            for($i = 0; $i < 6; $i++) {
                $k++;
                $right |= @strpos($this->B64, $ec{$k}) << ($i * 6);
            }
            for($i = 0; $i < 6; $i++) {
                $k++;
                $left |= @strpos($this->B64, $ec{$k}) << ($i * 6);
            }

            for($i = 0; $i < 4; $i++)
                $dc .= chr(($left & (0xFF << ((3 - $i) * 8))) >> ((3 - $i) * 8));

            for ($i = 0; $i < 4; $i++)
                $dc .= chr(($right & (0xFF << ((3 - $i) * 8))) >> ((3 - $i) * 8));

        }

        return $dc;
    }


Added this to the bot.conf. To remember how to add channels with blowfish.

Code
;====Blowfish support
;====blowfish <channel>
;====blowkey <key>
;====They have to be in that order to work, the first row with blowkey must be
;====the key to the channel specified in the first row with blowfish


Last edited by empty at 9:09 pm, Mar 15 2008

EHCanadian
Post #1050
user avatar
Member
Date: 8:20 pm, May 30 2010
Posts: 16


Could you provide a example format for the config area

------
Lag is the #1 killer!
   

Back to PHP-IRC Feature Requests