PageRenderTime 100ms CodeModel.GetById 28ms app.highlight 62ms RepoModel.GetById 1ms app.codeStats 0ms

/phpseclib/Crypt/DES.php

https://github.com/kea/phpseclib
PHP | 1297 lines | 776 code | 86 blank | 435 comment | 110 complexity | 482c165c22be1c3034bdfed521306a63 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   3
   4/**
   5 * Pure-PHP implementation of DES.
   6 *
   7 * Uses mcrypt, if available, and an internal implementation, otherwise.
   8 *
   9 * PHP versions 4 and 5
  10 *
  11 * Useful resources are as follows:
  12 *
  13 *  - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
  14 *  - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
  15 *  - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
  16 *
  17 * Here's a short example of how to use this library:
  18 * <code>
  19 * <?php
  20 *    include('Crypt/DES.php');
  21 *
  22 *    $des = new Crypt_DES();
  23 *
  24 *    $des->setKey('abcdefgh');
  25 *
  26 *    $size = 10 * 1024;
  27 *    $plaintext = '';
  28 *    for ($i = 0; $i < $size; $i++) {
  29 *        $plaintext.= 'a';
  30 *    }
  31 *
  32 *    echo $des->decrypt($des->encrypt($plaintext));
  33 * ?>
  34 * </code>
  35 *
  36 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  37 * of this software and associated documentation files (the "Software"), to deal
  38 * in the Software without restriction, including without limitation the rights
  39 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  40 * copies of the Software, and to permit persons to whom the Software is
  41 * furnished to do so, subject to the following conditions:
  42 *
  43 * The above copyright notice and this permission notice shall be included in
  44 * all copies or substantial portions of the Software.
  45 *
  46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  47 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  48 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  49 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  50 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  51 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  52 * THE SOFTWARE.
  53 *
  54 * @category   Crypt
  55 * @package    Crypt_DES
  56 * @author     Jim Wigginton <terrafrost@php.net>
  57 * @copyright  MMVII Jim Wigginton
  58 * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
  59 * @version    $Id: DES.php,v 1.12 2010/02/09 06:10:26 terrafrost Exp $
  60 * @link       http://phpseclib.sourceforge.net
  61 */
  62
  63namespace phpseclib;
  64
  65/**
  66 * Pure-PHP implementation of DES.
  67 *
  68 * @author  Jim Wigginton <terrafrost@php.net>
  69 * @version 0.1.0
  70 * @access  public
  71 * @package Crypt_DES
  72 */
  73class Crypt_DES {
  74    /**#@+
  75     * @access private
  76     * @see Crypt_DES::_prepareKey()
  77     * @see Crypt_DES::_processBlock()
  78     */
  79    /**
  80     * Contains array_reverse($keys[self::DECRYPT])
  81     */
  82    const ENCRYPT = 0;
  83    /**
  84     * Contains array_reverse($keys[self::ENCRYPT])
  85     */
  86    const DECRYPT = 1;
  87    /**#@-*/
  88
  89    /**#@+
  90     * @access public
  91     * @see Crypt_DES::encrypt()
  92     * @see Crypt_DES::decrypt()
  93     */
  94    /**
  95     * Encrypt / decrypt using the Counter mode.
  96     *
  97     * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
  98     *
  99     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
 100     */
 101    const MODE_CTR = -1;
 102    /**
 103     * Encrypt / decrypt using the Electronic Code Book mode.
 104     *
 105     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
 106     */
 107    const MODE_ECB = 1;
 108    /**
 109     * Encrypt / decrypt using the Code Book Chaining mode.
 110     *
 111     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
 112     */
 113    const MODE_CBC = 2;
 114    /**
 115     * Encrypt / decrypt using the Cipher Feedback mode.
 116     *
 117     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
 118     */
 119    const MODE_CFB = 3;
 120    /**
 121     * Encrypt / decrypt using the Cipher Feedback mode.
 122     *
 123     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
 124     */
 125    const MODE_OFB = 4;
 126    /**#@-*/
 127
 128    /**#@+
 129     * @access private
 130     * @see Crypt_DES::Crypt_DES()
 131     */
 132    /**
 133     * Toggles the internal implementation
 134     */
 135    const MODE_INTERNAL = 1;
 136    /**
 137     * Toggles the mcrypt implementation
 138     */
 139    const MODE_MCRYPT = 2;
 140    /**#@-*/
 141
 142    /**
 143     * The Key Schedule
 144     *
 145     * @see Crypt_DES::setKey()
 146     * @var Array
 147     * @access private
 148     */
 149    var $keys = "\0\0\0\0\0\0\0\0";
 150
 151    /**
 152     * The Encryption Mode
 153     *
 154     * @see Crypt_DES::Crypt_DES()
 155     * @var Integer
 156     * @access private
 157     */
 158    var $mode;
 159
 160    /**
 161     * Continuous Buffer status
 162     *
 163     * @see Crypt_DES::enableContinuousBuffer()
 164     * @var Boolean
 165     * @access private
 166     */
 167    var $continuousBuffer = false;
 168
 169    /**
 170     * Padding status
 171     *
 172     * @see Crypt_DES::enablePadding()
 173     * @var Boolean
 174     * @access private
 175     */
 176    var $padding = true;
 177
 178    /**
 179     * The Initialization Vector
 180     *
 181     * @see Crypt_DES::setIV()
 182     * @var String
 183     * @access private
 184     */
 185    var $iv = "\0\0\0\0\0\0\0\0";
 186
 187    /**
 188     * A "sliding" Initialization Vector
 189     *
 190     * @see Crypt_DES::enableContinuousBuffer()
 191     * @var String
 192     * @access private
 193     */
 194    var $encryptIV = "\0\0\0\0\0\0\0\0";
 195
 196    /**
 197     * A "sliding" Initialization Vector
 198     *
 199     * @see Crypt_DES::enableContinuousBuffer()
 200     * @var String
 201     * @access private
 202     */
 203    var $decryptIV = "\0\0\0\0\0\0\0\0";
 204
 205    /**
 206     * mcrypt resource for encryption
 207     *
 208     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
 209     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
 210     *
 211     * @see Crypt_DES::encrypt()
 212     * @var String
 213     * @access private
 214     */
 215    var $enmcrypt;
 216
 217    /**
 218     * mcrypt resource for decryption
 219     *
 220     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
 221     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
 222     *
 223     * @see Crypt_DES::decrypt()
 224     * @var String
 225     * @access private
 226     */
 227    var $demcrypt;
 228
 229    /**
 230     * Does the enmcrypt resource need to be (re)initialized?
 231     *
 232     * @see Crypt_DES::setKey()
 233     * @see Crypt_DES::setIV()
 234     * @var Boolean
 235     * @access private
 236     */
 237    var $enchanged = true;
 238
 239    /**
 240     * Does the demcrypt resource need to be (re)initialized?
 241     *
 242     * @see Crypt_DES::setKey()
 243     * @see Crypt_DES::setIV()
 244     * @var Boolean
 245     * @access private
 246     */
 247    var $dechanged = true;
 248
 249    /**
 250     * Is the mode one that is paddable?
 251     *
 252     * @see Crypt_DES::Crypt_DES()
 253     * @var Boolean
 254     * @access private
 255     */
 256    var $paddable = false;
 257
 258    /**
 259     * Encryption buffer for CTR, OFB and CFB modes
 260     *
 261     * @see Crypt_DES::encrypt()
 262     * @var String
 263     * @access private
 264     */
 265    var $enbuffer = '';
 266
 267    /**
 268     * Decryption buffer for CTR, OFB and CFB modes
 269     *
 270     * @see Crypt_DES::decrypt()
 271     * @var String
 272     * @access private
 273     */
 274    var $debuffer = '';
 275
 276    /**
 277     * mcrypt resource for CFB mode
 278     *
 279     * @see Crypt_DES::encrypt()
 280     * @see Crypt_DES::decrypt()
 281     * @var String
 282     * @access private
 283     */
 284    var $ecb;
 285
 286    /**
 287     * Default Constructor.
 288     *
 289     * Determines whether or not the mcrypt extension should be used.  $mode should only, at present, be
 290     * self::MODE_ECB or self::MODE_CBC.  If not explictly set, self::MODE_CBC will be used.
 291     *
 292     * @param optional Integer $mode
 293     * @return Crypt_DES
 294     * @access public
 295     */
 296    function __construct($mode = self::MODE_CBC)
 297    {
 298        if ( !defined('CRYPT_DES_MODE') ) {
 299            switch (true) {
 300                case extension_loaded('mcrypt') && in_array('des', mcrypt_list_algorithms()):
 301                    define('CRYPT_DES_MODE', self::MODE_MCRYPT);
 302                    break;
 303                default:
 304                    define('CRYPT_DES_MODE', self::MODE_INTERNAL);
 305            }
 306        }
 307
 308        switch ( CRYPT_DES_MODE ) {
 309            case self::MODE_MCRYPT:
 310                switch ($mode) {
 311                    case self::MODE_ECB:
 312                        $this->paddable = true;
 313                        $this->mode = MCRYPT_MODE_ECB;
 314                        break;
 315                    case self::MODE_CTR:
 316                        $this->mode = 'ctr';
 317                        //$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : self::MODE_CTR;
 318                        break;
 319                    case self::MODE_CFB:
 320                        $this->mode = 'ncfb';
 321                        break;
 322                    case self::MODE_OFB:
 323                        $this->mode = MCRYPT_MODE_NOFB;
 324                        break;
 325                    case self::MODE_CBC:
 326                    default:
 327                        $this->paddable = true;
 328                        $this->mode = MCRYPT_MODE_CBC;
 329                }
 330
 331                break;
 332            default:
 333                switch ($mode) {
 334                    case self::MODE_ECB:
 335                    case self::MODE_CBC:
 336                        $this->paddable = true;
 337                        $this->mode = $mode;
 338                        break;
 339                    case self::MODE_CTR:
 340                    case self::MODE_CFB:
 341                    case self::MODE_OFB:
 342                        $this->mode = $mode;
 343                        break;
 344                    default:
 345                        $this->paddable = true;
 346                        $this->mode = self::MODE_CBC;
 347                }
 348        }
 349    }
 350
 351    /**
 352     * Sets the key.
 353     *
 354     * Keys can be of any length.  DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
 355     * only use the first eight, if $key has more then eight characters in it, and pad $key with the
 356     * null byte if it is less then eight characters long.
 357     *
 358     * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
 359     *
 360     * If the key is not explicitly set, it'll be assumed to be all zero's.
 361     *
 362     * @access public
 363     * @param String $key
 364     */
 365    function setKey($key)
 366    {
 367        $this->keys = ( CRYPT_DES_MODE == self::MODE_MCRYPT ) ? str_pad(substr($key, 0, 8), 8, chr(0)) : $this->_prepareKey($key);
 368        $this->changed = true;
 369    }
 370
 371    /**
 372     * Sets the password.
 373     *
 374     * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
 375     *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
 376     *         $hash, $salt, $count
 377     *
 378     * @param String $password
 379     * @param optional String $method
 380     * @access public
 381     */
 382    function setPassword($password, $method = 'pbkdf2')
 383    {
 384        $key = '';
 385
 386        switch ($method) {
 387            default: // 'pbkdf2'
 388                //not the prettiest thing ever, but solves the undefined index issue with list()
 389                $args = func_get_args();
 390                $hash = 'sha1';
 391                $salt = 'phpseclib/salt';
 392                $count = 1000;
 393                switch(count($args)){
 394                    case 6:
 395                    case 5:
 396                        $count = $args[4];
 397                    case 4:
 398                        $salt = $args[3];
 399                    case 3:
 400                        $hash = $args[2];
 401                }
 402
 403                $i = 1;
 404                while (strlen($key) < 8) { // $dkLen == 8
 405                    //$dk.= $this->_pbkdf($password, $salt, $count, $i++);
 406                    $hmac = new Crypt_Hash();
 407                    $hmac->setHash($hash);
 408                    $hmac->setKey($password);
 409                    $f = $u = $hmac->hash($salt . pack('N', $i++));
 410                    for ($j = 2; $j <= $count; $j++) {
 411                        $u = $hmac->hash($u);
 412                        $f^= $u;
 413                    }
 414                    $key.= $f;
 415                }
 416        }
 417
 418        $this->setKey($key);
 419    }
 420
 421    /**
 422     * Sets the initialization vector. (optional)
 423     *
 424     * SetIV is not required when self::MODE_ECB is being used.  If not explictly set, it'll be assumed
 425     * to be all zero's.
 426     *
 427     * @access public
 428     * @param String $iv
 429     */
 430    function setIV($iv)
 431    {
 432        $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
 433        $this->changed = true;
 434    }
 435
 436    /**
 437     * Generate CTR XOR encryption key
 438     *
 439     * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
 440     * plaintext / ciphertext in CTR mode.
 441     *
 442     * @see Crypt_DES::decrypt()
 443     * @see Crypt_DES::encrypt()
 444     * @access public
 445     * @param Integer $length
 446     * @param String $iv
 447     */
 448    function _generate_xor($length, &$iv)
 449    {
 450        $xor = '';
 451        $num_blocks = ($length + 7) >> 3;
 452        for ($i = 0; $i < $num_blocks; $i++) {
 453            $xor.= $iv;
 454            for ($j = 4; $j <= 8; $j+=4) {
 455                $temp = substr($iv, -$j, 4);
 456                switch ($temp) {
 457                    case "\xFF\xFF\xFF\xFF":
 458                        $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
 459                    break;
 460                    case "\x7F\xFF\xFF\xFF":
 461                        $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
 462                    break 2;
 463                    default:
 464                    extract(unpack('Ncount', $temp));
 465                    $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
 466                    break 2;
 467                }
 468            }
 469        }
 470
 471        return $xor;
 472    }
 473
 474    /**
 475     * Encrypts a message.
 476     *
 477     * $plaintext will be padded with up to 8 additional bytes.  Other DES implementations may or may not pad in the
 478     * same manner.  Other common approaches to padding and the reasons why it's necessary are discussed in the following
 479     * URL:
 480     *
 481     * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
 482     *
 483     * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
 484     * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
 485     * length.
 486     *
 487     * @see Crypt_DES::decrypt()
 488     * @access public
 489     * @param String $plaintext
 490     */
 491    function encrypt($plaintext)
 492    {
 493        if ($this->paddable) {
 494            $plaintext = $this->_pad($plaintext);
 495        }
 496
 497        if ( CRYPT_DES_MODE == self::MODE_MCRYPT ) {
 498            if ($this->enchanged) {
 499                if (!isset($this->enmcrypt)) {
 500                    $this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
 501                }
 502                mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
 503                if ($this->mode != 'ncfb') {
 504                    $this->enchanged = false;
 505                }
 506            }
 507
 508            if ($this->mode != 'ncfb') {
 509                $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
 510            } else {
 511                if ($this->enchanged) {
 512                    $this->ecb = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
 513                    mcrypt_generic_init($this->ecb, $this->keys, "\0\0\0\0\0\0\0\0");
 514                    $this->enchanged = false;
 515                }
 516
 517                if (strlen($this->enbuffer)) {
 518                    $ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer));
 519                    $this->enbuffer.= $ciphertext;
 520                    if (strlen($this->enbuffer) == 8) {
 521                        $this->encryptIV = $this->enbuffer;
 522                        $this->enbuffer = '';
 523                        mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
 524                    }
 525                    $plaintext = substr($plaintext, strlen($ciphertext));
 526                } else {
 527                    $ciphertext = '';
 528                }
 529
 530                $last_pos = strlen($plaintext) & 0xFFFFFFF8;
 531                $ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : '';
 532
 533                if (strlen($plaintext) & 0x7) {
 534                    if (strlen($ciphertext)) {
 535                        $this->encryptIV = substr($ciphertext, -8);
 536                    }
 537                    $this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV);
 538                    $this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV;
 539                    $ciphertext.= $this->enbuffer;
 540                }
 541            }
 542
 543            if (!$this->continuousBuffer) {
 544                mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
 545            }
 546
 547            return $ciphertext;
 548        }
 549
 550        if (!is_array($this->keys)) {
 551            $this->keys = $this->_prepareKey("\0\0\0\0\0\0\0\0");
 552        }
 553
 554        $buffer = &$this->enbuffer;
 555        $continuousBuffer = $this->continuousBuffer;
 556        $ciphertext = '';
 557        switch ($this->mode) {
 558            case self::MODE_ECB:
 559                for ($i = 0; $i < strlen($plaintext); $i+=8) {
 560                    $ciphertext.= $this->_processBlock(substr($plaintext, $i, 8), self::ENCRYPT);
 561                }
 562                break;
 563            case self::MODE_CBC:
 564                $xor = $this->encryptIV;
 565                for ($i = 0; $i < strlen($plaintext); $i+=8) {
 566                    $block = substr($plaintext, $i, 8);
 567                    $block = $this->_processBlock($block ^ $xor, self::ENCRYPT);
 568                    $xor = $block;
 569                    $ciphertext.= $block;
 570                }
 571                if ($this->continuousBuffer) {
 572                    $this->encryptIV = $xor;
 573                }
 574                break;
 575            case self::MODE_CTR:
 576                $xor = $this->encryptIV;
 577                if (strlen($buffer['encrypted'])) {
 578                    for ($i = 0; $i < strlen($plaintext); $i+=8) {
 579                        $block = substr($plaintext, $i, 8);
 580                        $buffer['encrypted'].= $this->_processBlock($this->_generate_xor(8, $xor), self::ENCRYPT);
 581                        $key = $this->_string_shift($buffer['encrypted'], 8);
 582                        $ciphertext.= $block ^ $key;
 583                    }
 584                } else {
 585                    for ($i = 0; $i < strlen($plaintext); $i+=8) {
 586                        $block = substr($plaintext, $i, 8);
 587                        $key = $this->_processBlock($this->_generate_xor(8, $xor), self::ENCRYPT);
 588                        $ciphertext.= $block ^ $key;
 589                    }
 590                }
 591                if ($this->continuousBuffer) {
 592                    $this->encryptIV = $xor;
 593                    if ($start = strlen($plaintext) & 7) {
 594                        $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
 595                    }
 596                }
 597                break;
 598            case self::MODE_CFB:
 599                if (!empty($buffer['xor'])) {
 600                    $ciphertext = $plaintext ^ $buffer['xor'];
 601                    $iv = $buffer['encrypted'] . $ciphertext;
 602                    $start = strlen($ciphertext);
 603                    $buffer['encrypted'].= $ciphertext;
 604                    $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
 605                } else {
 606                    $ciphertext = '';
 607                    $iv = $this->encryptIV;
 608                    $start = 0;
 609                }
 610
 611                for ($i = $start; $i < strlen($plaintext); $i+=8) {
 612                    $block = substr($plaintext, $i, 8);
 613                    $xor = $this->_processBlock($iv, self::ENCRYPT);
 614                    $iv = $block ^ $xor;
 615                    if ($continuousBuffer && strlen($iv) != 8) {
 616                        $buffer = array(
 617                                'encrypted' => $iv,
 618                                'xor' => substr($xor, strlen($iv))
 619                                );
 620                    }
 621                    $ciphertext.= $iv;
 622                }
 623
 624                if ($this->continuousBuffer) {
 625                    $this->encryptIV = $iv;
 626                }
 627                break;
 628            case self::MODE_OFB:
 629                $xor = $this->encryptIV;
 630                if (strlen($buffer)) {
 631                    for ($i = 0; $i < strlen($plaintext); $i+=8) {
 632                        $xor = $this->_processBlock($xor, self::ENCRYPT);
 633                        $buffer.= $xor;
 634                        $key = $this->_string_shift($buffer, 8);
 635                        $ciphertext.= substr($plaintext, $i, 8) ^ $key;
 636                    }
 637                } else {
 638                    for ($i = 0; $i < strlen($plaintext); $i+=8) {
 639                        $xor = $this->_processBlock($xor, self::ENCRYPT);
 640                        $ciphertext.= substr($plaintext, $i, 8) ^ $xor;
 641                    }
 642                    $key = $xor;
 643                }
 644                if ($this->continuousBuffer) {
 645                    $this->encryptIV = $xor;
 646                    if ($start = strlen($plaintext) & 7) {
 647                        $buffer = substr($key, $start) . $buffer;
 648                    }
 649                }
 650        }
 651
 652        return $ciphertext;
 653    }
 654
 655    /**
 656     * Decrypts a message.
 657     *
 658     * If strlen($ciphertext) is not a multiple of 8, null bytes will be added to the end of the string until it is.
 659     *
 660     * @see Crypt_DES::encrypt()
 661     * @access public
 662     * @param String $ciphertext
 663     */
 664    function decrypt($ciphertext)
 665    {
 666        if ($this->paddable) {
 667            // we pad with chr(0) since that's what mcrypt_generic does.  to quote from http://php.net/function.mcrypt-generic :
 668            // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
 669            $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
 670        }
 671
 672        if ( CRYPT_DES_MODE == self::MODE_MCRYPT ) {
 673            if ($this->dechanged) {
 674                if (!isset($this->demcrypt)) {
 675                    $this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
 676                }
 677                mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
 678                if ($this->mode != 'ncfb') {
 679                    $this->dechanged = false;
 680                }
 681            }
 682
 683            if ($this->mode != 'ncfb') {
 684                $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
 685            } else {
 686                if ($this->dechanged) {
 687                    $this->ecb = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
 688                    mcrypt_generic_init($this->ecb, $this->keys, "\0\0\0\0\0\0\0\0");
 689                    $this->dechanged = false;
 690                }
 691
 692                if (strlen($this->debuffer)) {
 693                    $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer));
 694
 695                    $this->debuffer.= substr($ciphertext, 0, strlen($plaintext));
 696                    if (strlen($this->debuffer) == 8) {
 697                        $this->decryptIV = $this->debuffer;
 698                        $this->debuffer = '';
 699                        mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
 700                    }
 701                    $ciphertext = substr($ciphertext, strlen($plaintext));
 702                } else {
 703                    $plaintext = '';
 704                }
 705
 706                $last_pos = strlen($ciphertext) & 0xFFFFFFF8;
 707                $plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : '';
 708
 709                if (strlen($ciphertext) & 0x7) {
 710                    if (strlen($plaintext)) {
 711                        $this->decryptIV = substr($ciphertext, $last_pos - 8, 8);
 712                    }
 713                    $this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV);
 714                    $this->debuffer = substr($ciphertext, $last_pos);
 715                    $plaintext.= $this->debuffer ^ $this->decryptIV;
 716                }
 717
 718                return $plaintext;
 719            }
 720
 721            if (!$this->continuousBuffer) {
 722                mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
 723            }
 724
 725            $ret = $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
 726            return $ret;
 727        }
 728
 729        if (!is_array($this->keys)) {
 730            $this->keys = $this->_prepareKey("\0\0\0\0\0\0\0\0");
 731        }
 732
 733        $buffer = &$this->debuffer;
 734        $continuousBuffer = $this->continuousBuffer;
 735        $plaintext = '';
 736        switch ($this->mode) {
 737            case self::MODE_ECB:
 738                for ($i = 0; $i < strlen($ciphertext); $i+=8) {
 739                    $plaintext.= $this->_processBlock(substr($ciphertext, $i, 8), self::DECRYPT);
 740                }
 741                break;
 742            case self::MODE_CBC:
 743                $xor = $this->decryptIV;
 744                for ($i = 0; $i < strlen($ciphertext); $i+=8) {
 745                    $block = substr($ciphertext, $i, 8);
 746                    $plaintext.= $this->_processBlock($block, self::DECRYPT) ^ $xor;
 747                    $xor = $block;
 748                }
 749                if ($this->continuousBuffer) {
 750                    $this->decryptIV = $xor;
 751                }
 752                break;
 753            case self::MODE_CTR:
 754                $xor = $this->decryptIV;
 755                if (strlen($buffer['ciphertext'])) {
 756                    for ($i = 0; $i < strlen($ciphertext); $i+=8) {
 757                        $block = substr($ciphertext, $i, 8);
 758                        $buffer['ciphertext'].= $this->_processBlock($this->_generate_xor(8, $xor), self::ENCRYPT);
 759                        $key = $this->_string_shift($buffer['ciphertext'], 8);
 760                        $plaintext.= $block ^ $key;
 761                    }
 762                } else {
 763                    for ($i = 0; $i < strlen($ciphertext); $i+=8) {
 764                        $block = substr($ciphertext, $i, 8);
 765                        $key = $this->_processBlock($this->_generate_xor(8, $xor), self::ENCRYPT);
 766                        $plaintext.= $block ^ $key;
 767                    }
 768                }
 769                if ($this->continuousBuffer) {
 770                    $this->decryptIV = $xor;
 771                    if ($start = strlen($ciphertext) % 8) {
 772                        $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
 773                    }
 774                }
 775                break;
 776            case self::MODE_CFB:
 777                if (!empty($buffer['ciphertext'])) {
 778                    $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext']));
 779                    $buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext));
 780                    if (strlen($buffer['ciphertext']) == 8) {
 781                        $xor = $this->_processBlock($buffer['ciphertext'], self::ENCRYPT);
 782                        $buffer['ciphertext'] = '';
 783                    }
 784                    $start = strlen($plaintext);
 785                    $block = $this->decryptIV;
 786                } else {
 787                    $plaintext = '';
 788                    $xor = $this->_processBlock($this->decryptIV, self::ENCRYPT);
 789                    $start = 0;
 790                }
 791
 792                for ($i = $start; $i < strlen($ciphertext); $i+=8) {
 793                    $block = substr($ciphertext, $i, 8);
 794                    $plaintext.= $block ^ $xor;
 795                    if ($continuousBuffer && strlen($block) != 8) {
 796                        $buffer['ciphertext'].= $block;
 797                        $block = $xor;
 798                    } else if (strlen($block) == 8) {
 799                        $xor = $this->_processBlock($block, self::ENCRYPT);
 800                    }
 801                }
 802                if ($this->continuousBuffer) {
 803                    $this->decryptIV = $block;
 804                }
 805                break;
 806            case self::MODE_OFB:
 807                $xor = $this->decryptIV;
 808                if (strlen($buffer)) {
 809                    for ($i = 0; $i < strlen($ciphertext); $i+=8) {
 810                        $xor = $this->_processBlock($xor, self::ENCRYPT);
 811                        $buffer.= $xor;
 812                        $key = $this->_string_shift($buffer, 8);
 813                        $plaintext.= substr($ciphertext, $i, 8) ^ $key;
 814                    }
 815                } else {
 816                    for ($i = 0; $i < strlen($ciphertext); $i+=8) {
 817                        $xor = $this->_processBlock($xor, self::ENCRYPT);
 818                        $plaintext.= substr($ciphertext, $i, 8) ^ $xor;
 819                    }
 820                    $key = $xor;
 821                }
 822                if ($this->continuousBuffer) {
 823                    $this->decryptIV = $xor;
 824                    if ($start = strlen($ciphertext) % 8) {
 825                        $buffer = substr($key, $start) . $buffer;
 826                    }
 827                }
 828        }
 829
 830        return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
 831    }
 832
 833    /**
 834     * Treat consecutive "packets" as if they are a continuous buffer.
 835     *
 836     * Say you have a 16-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
 837     * will yield different outputs:
 838     *
 839     * <code>
 840     *    echo $des->encrypt(substr($plaintext, 0, 8));
 841     *    echo $des->encrypt(substr($plaintext, 8, 8));
 842     * </code>
 843     * <code>
 844     *    echo $des->encrypt($plaintext);
 845     * </code>
 846     *
 847     * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
 848     * another, as demonstrated with the following:
 849     *
 850     * <code>
 851     *    $des->encrypt(substr($plaintext, 0, 8));
 852     *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
 853     * </code>
 854     * <code>
 855     *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
 856     * </code>
 857     *
 858     * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
 859     * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
 860     * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
 861     *
 862     * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
 863     * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
 864     * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
 865     * however, they are also less intuitive and more likely to cause you problems.
 866     *
 867     * @see Crypt_DES::disableContinuousBuffer()
 868     * @access public
 869     */
 870    function enableContinuousBuffer()
 871    {
 872        $this->continuousBuffer = true;
 873    }
 874
 875    /**
 876     * Treat consecutive packets as if they are a discontinuous buffer.
 877     *
 878     * The default behavior.
 879     *
 880     * @see Crypt_DES::enableContinuousBuffer()
 881     * @access public
 882     */
 883    function disableContinuousBuffer()
 884    {
 885        $this->continuousBuffer = false;
 886        $this->encryptIV = $this->iv;
 887        $this->decryptIV = $this->iv;
 888    }
 889
 890    /**
 891     * Pad "packets".
 892     *
 893     * DES works by encrypting eight bytes at a time.  If you ever need to encrypt or decrypt something that's not
 894     * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
 895     *
 896     * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH1,
 897     * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
 898     * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
 899     * transmitted separately)
 900     *
 901     * @see Crypt_DES::disablePadding()
 902     * @access public
 903     */
 904    function enablePadding()
 905    {
 906        $this->padding = true;
 907    }
 908
 909    /**
 910     * Do not pad packets.
 911     *
 912     * @see Crypt_DES::enablePadding()
 913     * @access public
 914     */
 915    function disablePadding()
 916    {
 917        $this->padding = false;
 918    }
 919
 920    /**
 921     * Pads a string
 922     *
 923     * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
 924     * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
 925     *
 926     * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
 927     * and padding will, hence forth, be enabled.
 928     *
 929     * @see Crypt_DES::_unpad()
 930     * @access private
 931     */
 932    function _pad($text)
 933    {
 934        if(!$this->paddable)
 935            return $text;
 936        $length = strlen($text);
 937
 938        if (!$this->padding) {
 939            if (($length & 7) == 0) {
 940                return $text;
 941            } else {
 942                user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_WARNING);
 943                $this->padding = true;
 944            }
 945        }
 946
 947        $pad = 8 - ($length & 7);
 948        return str_pad($text, $length + $pad, chr($pad));
 949    }
 950
 951    /**
 952     * Unpads a string
 953     *
 954     * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
 955     * and false will be returned.
 956     *
 957     * @see Crypt_DES::_pad()
 958     * @access private
 959     */
 960    function _unpad($text)
 961    {
 962        if (!$this->padding || !$this->paddable) {
 963            return $text;
 964        }
 965
 966        $length = ord($text[strlen($text) - 1]);
 967
 968        if (!$length || $length > 8) {
 969            return false;
 970        }
 971
 972        return substr($text, 0, -$length);
 973    }
 974
 975    /**
 976     * Encrypts or decrypts a 64-bit block
 977     *
 978     * $mode should be either self::ENCRYPT or self::DECRYPT.  See
 979     * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
 980     * idea of what this function does.
 981     *
 982     * @access private
 983     * @param String $block
 984     * @param Integer $mode
 985     * @return String
 986     */
 987    function _processBlock($block, $mode)
 988    {
 989        // s-boxes.  in the official DES docs, they're described as being matrices that
 990        // one accesses by using the first and last bits to determine the row and the
 991        // middle four bits to determine the column.  in this implementation, they've
 992        // been converted to vectors
 993        static $sbox = array(
 994                array(
 995                    14,  0,  4, 15, 13,  7,  1,  4,  2, 14, 15,  2, 11, 13,  8,  1,
 996                    3, 10 ,10,  6,  6, 12, 12, 11,  5,  9,  9,  5,  0,  3,  7,  8,
 997                    4, 15,  1, 12, 14,  8,  8,  2, 13,  4,  6,  9,  2,  1, 11,  7,
 998                    15,  5, 12, 11,  9,  3,  7, 14,  3, 10, 10,  0,  5,  6,  0, 13
 999                    ),
1000                array(
1001                    15,  3,  1, 13,  8,  4, 14,  7,  6, 15, 11,  2,  3,  8,  4, 14,
1002                    9, 12,  7,  0,  2,  1, 13, 10, 12,  6,  0,  9,  5, 11, 10,  5,
1003                    0, 13, 14,  8,  7, 10, 11,  1, 10,  3,  4, 15, 13,  4,  1,  2,
1004                    5, 11,  8,  6, 12,  7,  6, 12,  9,  0,  3,  5,  2, 14, 15,  9
1005                    ),
1006                array(
1007                    10, 13,  0,  7,  9,  0, 14,  9,  6,  3,  3,  4, 15,  6,  5, 10,
1008                    1,  2, 13,  8, 12,  5,  7, 14, 11, 12,  4, 11,  2, 15,  8,  1,
1009                    13,  1,  6, 10,  4, 13,  9,  0,  8,  6, 15,  9,  3,  8,  0,  7,
1010                    11,  4,  1, 15,  2, 14, 12,  3,  5, 11, 10,  5, 14,  2,  7, 12
1011                    ),
1012                array(
1013                    7, 13, 13,  8, 14, 11,  3,  5,  0,  6,  6, 15,  9,  0, 10,  3,
1014                    1,  4,  2,  7,  8,  2,  5, 12, 11,  1, 12, 10,  4, 14, 15,  9,
1015                    10,  3,  6, 15,  9,  0,  0,  6, 12, 10, 11,  1,  7, 13, 13,  8,
1016                    15,  9,  1,  4,  3,  5, 14, 11,  5, 12,  2,  7,  8,  2,  4, 14
1017                    ),
1018                array(
1019                        2, 14, 12, 11,  4,  2,  1, 12,  7,  4, 10,  7, 11, 13,  6,  1,
1020                        8,  5,  5,  0,  3, 15, 15, 10, 13,  3,  0,  9, 14,  8,  9,  6,
1021                        4, 11,  2,  8,  1, 12, 11,  7, 10,  1, 13, 14,  7,  2,  8, 13,
1022                        15,  6,  9, 15, 12,  0,  5,  9,  6, 10,  3,  4,  0,  5, 14,  3
1023                     ),
1024                array(
1025                        12, 10,  1, 15, 10,  4, 15,  2,  9,  7,  2, 12,  6,  9,  8,  5,
1026                        0,  6, 13,  1,  3, 13,  4, 14, 14,  0,  7, 11,  5,  3, 11,  8,
1027                        9,  4, 14,  3, 15,  2,  5, 12,  2,  9,  8,  5, 12, 15,  3, 10,
1028                        7, 11,  0, 14,  4,  1, 10,  7,  1,  6, 13,  0, 11,  8,  6, 13
1029                     ),
1030                array(
1031                        4, 13, 11,  0,  2, 11, 14,  7, 15,  4,  0,  9,  8,  1, 13, 10,
1032                        3, 14, 12,  3,  9,  5,  7, 12,  5,  2, 10, 15,  6,  8,  1,  6,
1033                        1,  6,  4, 11, 11, 13, 13,  8, 12,  1,  3,  4,  7, 10, 14,  7,
1034                        10,  9, 15,  5,  6,  0,  8, 15,  0, 14,  5,  2,  9,  3,  2, 12
1035                     ),
1036                array(
1037                        13,  1,  2, 15,  8, 13,  4,  8,  6, 10, 15,  3, 11,  7,  1,  4,
1038                        10, 12,  9,  5,  3,  6, 14, 11,  5,  0,  0, 14, 12,  9,  7,  2,
1039                        7,  2, 11,  1,  4, 14,  1,  7,  9,  4, 12, 10, 14,  8,  2, 13,
1040                        0, 15,  6, 12, 10,  9, 13,  0, 15,  3,  3,  5,  5,  6,  8, 11
1041                     )
1042                    );
1043
1044        $keys = $this->keys;
1045
1046        $temp = unpack('Na/Nb', $block);
1047        $block = array($temp['a'], $temp['b']);
1048
1049        // because php does arithmetic right shifts, if the most significant bits are set, right
1050        // shifting those into the correct position will add 1's - not 0's.  this will intefere
1051        // with the | operation unless a second & is done.  so we isolate these bits and left shift
1052        // them into place.  we then & each block with 0x7FFFFFFF to prevennt 1's from being added
1053        // for any other shifts.
1054        $msb = array(
1055                ($block[0] >> 31) & 1,
1056                ($block[1] >> 31) & 1
1057                );
1058        $block[0] &= 0x7FFFFFFF;
1059        $block[1] &= 0x7FFFFFFF;
1060
1061        // we isolate the appropriate bit in the appropriate integer and shift as appropriate.  in
1062        // some cases, there are going to be multiple bits in the same integer that need to be shifted
1063        // in the same way.  we combine those into one shift operation.
1064        $block = array(
1065                (($block[1] & 0x00000040) << 25) | (($block[1] & 0x00004000) << 16) |
1066                (($block[1] & 0x00400001) <<  7) | (($block[1] & 0x40000100) >>  2) |
1067                (($block[0] & 0x00000040) << 21) | (($block[0] & 0x00004000) << 12) |
1068                (($block[0] & 0x00400001) <<  3) | (($block[0] & 0x40000100) >>  6) |
1069                (($block[1] & 0x00000010) << 19) | (($block[1] & 0x00001000) << 10) |
1070                (($block[1] & 0x00100000) <<  1) | (($block[1] & 0x10000000) >>  8) |
1071                (($block[0] & 0x00000010) << 15) | (($block[0] & 0x00001000) <<  6) |
1072                (($block[0] & 0x00100000) >>  3) | (($block[0] & 0x10000000) >> 12) |
1073                (($block[1] & 0x00000004) << 13) | (($block[1] & 0x00000400) <<  4) |
1074                (($block[1] & 0x00040000) >>  5) | (($block[1] & 0x04000000) >> 14) |
1075                (($block[0] & 0x00000004) <<  9) | ( $block[0] & 0x00000400       ) |
1076                (($block[0] & 0x00040000) >>  9) | (($block[0] & 0x04000000) >> 18) |
1077                (($block[1] & 0x00010000) >> 11) | (($block[1] & 0x01000000) >> 20) |
1078                (($block[0] & 0x00010000) >> 15) | (($block[0] & 0x01000000) >> 24)
1079                ,
1080                (($block[1] & 0x00000080) << 24) | (($block[1] & 0x00008000) << 15) |
1081                (($block[1] & 0x00800002) <<  6) | (($block[0] & 0x00000080) << 20) |
1082                (($block[0] & 0x00008000) << 11) | (($block[0] & 0x00800002) <<  2) |
1083                (($block[1] & 0x00000020) << 18) | (($block[1] & 0x00002000) <<  9) |
1084                ( $block[1] & 0x00200000       ) | (($block[1] & 0x20000000) >>  9) |
1085                (($block[0] & 0x00000020) << 14) | (($block[0] & 0x00002000) <<  5) |
1086                (($block[0] & 0x00200000) >>  4) | (($block[0] & 0x20000000) >> 13) |
1087                (($block[1] & 0x00000008) << 12) | (($block[1] & 0x00000800) <<  3) |
1088                (($block[1] & 0x00080000) >>  6) | (($block[1] & 0x08000000) >> 15) |
1089                (($block[0] & 0x00000008) <<  8) | (($block[0] & 0x00000800) >>  1) |
1090                (($block[0] & 0x00080000) >> 10) | (($block[0] & 0x08000000) >> 19) |
1091                (($block[1] & 0x00000200) >>  3) | (($block[0] & 0x00000200) >>  7) |
1092                (($block[1] & 0x00020000) >> 12) | (($block[1] & 0x02000000) >> 21) |
1093                (($block[0] & 0x00020000) >> 16) | (($block[0] & 0x02000000) >> 25) |
1094                ($msb[1] << 28) | ($msb[0] << 24)
1095                );
1096
1097        for ($i = 0; $i < 16; $i++) {
1098            // start of "the Feistel (F) function" - see the following URL:
1099            // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
1100            $temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $keys[$mode][$i][0]]) << 28)
1101                | (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $keys[$mode][$i][1]]) << 24)
1102                | (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $keys[$mode][$i][2]]) << 20)
1103                | (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $keys[$mode][$i][3]]) << 16)
1104                | (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $keys[$mode][$i][4]]) << 12)
1105                | (($sbox[5][(($block[1] & 0x00001F80) >>  7) ^ $keys[$mode][$i][5]]) <<  8)
1106                | (($sbox[6][(($block[1] & 0x000001F8) >>  3) ^ $keys[$mode][$i][6]]) <<  4)
1107                | ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $keys[$mode][$i][7]]);
1108
1109            $msb = ($temp >> 31) & 1;
1110            $temp &= 0x7FFFFFFF;
1111            $newBlock = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) <<  5)
1112                | (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10)
1113                | (($temp & 0x00000008) << 24) | (($temp & 0x00100000) <<  6)
1114                | (($temp & 0x00000010) << 21) | (($temp & 0x00008000) <<  9)
1115                | (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27)
1116                | (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >>  8)
1117                | (($temp & 0x00004000) <<  4) | (($temp & 0x00000002) << 16)
1118                | (($temp & 0x00442000) >>  6) | (($temp & 0x40800000) >> 15)
1119                | (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20)
1120                | (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) <<  3)
1121                | (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >>  7)
1122                | (($temp & 0x00200000) >> 19) | ($msb << 23);
1123            // end of "the Feistel (F) function" - $newBlock is F's output
1124
1125            $temp = $block[1];
1126            $block[1] = $block[0] ^ $newBlock;
1127            $block[0] = $temp;
1128        }
1129
1130        $msb = array(
1131                ($block[0] >> 31) & 1,
1132                ($block[1] >> 31) & 1
1133                );
1134        $block[0] &= 0x7FFFFFFF;
1135        $block[1] &= 0x7FFFFFFF;
1136
1137        $block = array(
1138                (($block[0] & 0x01000004) <<  7) | (($block[1] & 0x01000004) <<  6) |
1139                (($block[0] & 0x00010000) << 13) | (($block[1] & 0x00010000) << 12) |
1140                (($block[0] & 0x00000100) << 19) | (($block[1] & 0x00000100) << 18) |
1141                (($block[0] & 0x00000001) << 25) | (($block[1] & 0x00000001) << 24) |
1142                (($block[0] & 0x02000008) >>  2) | (($block[1] & 0x02000008) >>  3) |
1143                (($block[0] & 0x00020000) <<  4) | (($block[1] & 0x00020000) <<  3) |
1144                (($block[0] & 0x00000200) << 10) | (($block[1] & 0x00000200) <<  9) |
1145                (($block[0] & 0x00000002) << 16) | (($block[1] & 0x00000002) << 15) |
1146                (($block[0] & 0x04000000) >> 11) | (($block[1] & 0x04000000) >> 12) |
1147                (($block[0] & 0x00040000) >>  5) | (($block[1] & 0x00040000) >>  6) |
1148                (($block[0] & 0x00000400) <<  1) | ( $block[1] & 0x00000400       ) |
1149                (($block[0] & 0x08000000) >> 20) | (($block[1] & 0x08000000) >> 21) |
1150                (($block[0] & 0x00080000) >> 14) | (($block[1] & 0x00080000) >> 15) |
1151                (($block[0] & 0x00000800) >>  8) | (($block[1] & 0x00000800) >>  9)
1152                ,
1153                (($block[0] & 0x10000040) <<  3) | (($block[1] & 0x10000040) <<  2) |
1154                (($block[0] & 0x00100000) <<  9) | (($block[1] & 0x00100000) <<  8) |
1155                (($block[0] & 0x00001000) << 15) | (($block[1] & 0x00001000) << 14) |
1156                (($block[0] & 0x00000010) << 21) | (($block[1] & 0x00000010) << 20) |
1157                (($block[0] & 0x20000080) >>  6) | (($block[1] & 0x20000080) >>  7) |
1158                ( $block[0] & 0x00200000       ) | (($block[1] & 0x00200000) >>  1) |
1159                (($block[0] & 0x00002000) <<  6) | (($block[1] & 0x00002000) <<  5) |
1160                (($block[0] & 0x00000020) << 12) | (($block[1] & 0x00000020) << 11) |
1161                (($block[0] & 0x40000000) >> 15) | (($block[1] & 0x40000000) >> 16) |
1162                (($block[0] & 0x00400000) >>  9) | (($block[1] & 0x00400000) >> 10) |
1163                (($block[0] & 0x00004000) >>  3) | (($block[1] & 0x00004000) >>  4) |
1164                (($block[0] & 0x00800000) >> 18) | (($block[1] & 0x00800000) >> 19) |
1165                (($block[0] & 0x00008000) >> 12) | (($block[1] & 0x00008000) >> 13) |
1166                ($msb[0] <<  7) | ($msb[1] <<  6)
1167                );
1168
1169        return pack('NN', $block[0], $block[1]);
1170    }
1171
1172    /**
1173     * Creates the key schedule.
1174     *
1175     * @access private
1176     * @param String $key
1177     * @return Array
1178     */
1179    function _prepareKey($key)
1180    {
1181        static $shifts = array( // number of key bits shifted per round
1182                1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
1183                );
1184
1185        // pad the key and remove extra characters as appropriate.
1186        $key = str_pad(substr($key, 0, 8), 8, chr(0));
1187
1188        $temp = unpack('Na/Nb', $key);
1189        $key = array($temp['a'], $temp['b']);
1190        $msb = array(
1191                ($key[0] >> 31) & 1,
1192                ($key[1] >> 31) & 1
1193                );
1194        $key[0] &= 0x7FFFFFFF;
1195        $key[1] &= 0x7FFFFFFF;
1196
1197        $key = array(
1198                (($key[1] & 0x00000002) << 26) | (($key[1] & 0x00000204) << 17) |
1199                (($key[1] & 0x00020408) <<  8) | (($key[1] & 0x02040800) >>  1) |
1200                (($key[0] & 0x00000002) << 22) | (($key[0] & 0x00000204) << 13) |
1201                (($key[0] & 0x00020408) <<  4) | (($key[0] & 0x02040800) >>  5) |
1202                (($key[1] & 0x04080000) >> 10) | (($key[0] & 0x04080000) >> 14) |
1203                (($key[1] & 0x08000000) >> 19) | (($key[0] & 0x08000000) >> 23) |
1204                (($key[0] & 0x00000010) >>  1) | (($key[0] & 0x00001000) >> 10) |
1205                (($key[0] & 0x00100000) >> 19) | (($key[0] & 0x10000000) >> 28)
1206                ,
1207                (($key[1] & 0x00000080) << 20) | (($key[1] & 0x00008000) << 11) |
1208                (($key[1] & 0x00800000) <<  2) | (($key[0] & 0x00000080) << 16) |
1209                (($key[0] & 0x00008000) <<  7) | (($key[0] & 0x00800000) >>  2) |
1210                (($key[1] & 0x00000040) << 13) | (($key[1] & 0x00004000) <<  4) |
1211                (($key[1] & 0x00400000) >>  5) | (($key[1] & 0x40000000) >> 14) |
1212                (($key[0] & 0x00000040) <<  9) | ( $key[0] & 0x00004000       ) |
1213                (($key[0] & 0x00400000) >>  9) | (($key[0] & 0x40000000) >> 18) |
1214                (($key[1] & 0x00000020) <<  6) | (($key[1] & 0x00002000) >>  3) |
1215                (($key[1] & 0x00200000) >> 12) | (($key[1] & 0x20000000) >> 21) |
1216                (($key[0] & 0x00000020) <<  2) | (($key[0] & 0x00002000) >>  7) |
1217                (($key[0] & 0x00200000) >> 16) | (($key[0] & 0x20000000) >> 25) |
1218                (($key[1] & 0x00000010) >>  1) | (($key[1] & 0x00001000) >> 10) |
1219                (($key[1] & 0x00100000) >> 19) | (($key[1] & 0x10000000) >> 28) |
1220                ($msb[1] << 24) | ($msb[0] << 20)
1221                );
1222
1223        $keys = array();
1224        for ($i = 0; $i < 16; $i++) {
1225            $key[0] <<= $shifts[$i];
1226            $temp = ($key[0] & 0xF0000000) >> 28;
1227            $key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
1228
1229            $key[1] <<= $shifts[$i];
1230            $temp = ($key[1] & 0xF0000000) >> 28;
1231            $key[1] = ($key[1] | $temp) & 0x0FFFFFFF;
1232
1233            $temp = array(
1234                    (($key[1] & 0x00004000) >>  9) | (($key[1] & 0x00000800) >>  7) |
1235                    (($key[1] & 0x00020000) >> 14) | (($key[1] & 0x00000010) >>  2) |
1236                    (($key[1] & 0x08000000) >> 26) | (($key[1] & 0x00800000) >> 23)
1237                    ,
1238                    (($key[1] & 0x02400000) >> 20) | (($key[1] & 0x00000001) <<  4) |
1239                    (($key[1] & 0x00002000) >> 10) | (($key[1] & 0x00040000) >> 18) |
1240                    (($key[1] & 0x00000080) >>  6)
1241                    ,
1242                    ( $key[1] & 0x00000020       ) | (($key[1] & 0x00000200) >>  5) |
1243                    (($key[1] & 0x00010000) >> 13) | (($key[1] & 0x010000

Large files files are truncated, but you can click here to view the full file