Subversion Repositories oidplus

Rev

Rev 846 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /**
  4.  * Pure-PHP implementation of Triple DES.
  5.  *
  6.  * Uses mcrypt, if available, and an internal implementation, otherwise.  Operates in the EDE3 mode (encrypt-decrypt-encrypt).
  7.  *
  8.  * PHP version 5
  9.  *
  10.  * Here's a short example of how to use this library:
  11.  * <code>
  12.  * <?php
  13.  *    include 'vendor/autoload.php';
  14.  *
  15.  *    $des = new \phpseclib3\Crypt\TripleDES('ctr');
  16.  *
  17.  *    $des->setKey('abcdefghijklmnopqrstuvwx');
  18.  *
  19.  *    $size = 10 * 1024;
  20.  *    $plaintext = '';
  21.  *    for ($i = 0; $i < $size; $i++) {
  22.  *        $plaintext.= 'a';
  23.  *    }
  24.  *
  25.  *    echo $des->decrypt($des->encrypt($plaintext));
  26.  * ?>
  27.  * </code>
  28.  *
  29.  * @category  Crypt
  30.  * @package   TripleDES
  31.  * @author    Jim Wigginton <terrafrost@php.net>
  32.  * @copyright 2007 Jim Wigginton
  33.  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  34.  * @link      http://phpseclib.sourceforge.net
  35.  */
  36.  
  37. namespace phpseclib3\Crypt;
  38.  
  39. /**
  40.  * Pure-PHP implementation of Triple DES.
  41.  *
  42.  * @package TripleDES
  43.  * @author  Jim Wigginton <terrafrost@php.net>
  44.  * @access  public
  45.  */
  46. class TripleDES extends DES
  47. {
  48.     /**
  49.      * Encrypt / decrypt using inner chaining
  50.      *
  51.      * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
  52.      */
  53.     const MODE_3CBC = -2;
  54.  
  55.     /**
  56.      * Encrypt / decrypt using outer chaining
  57.      *
  58.      * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib3\Crypt\Common\BlockCipher::MODE_CBC.
  59.      */
  60.     const MODE_CBC3 = self::MODE_CBC;
  61.  
  62.     /**
  63.      * Key Length (in bytes)
  64.      *
  65.      * @see \phpseclib3\Crypt\TripleDES::setKeyLength()
  66.      * @var int
  67.      * @access private
  68.      */
  69.     protected $key_length = 24;
  70.  
  71.     /**
  72.      * The mcrypt specific name of the cipher
  73.      *
  74.      * @see \phpseclib3\Crypt\DES::cipher_name_mcrypt
  75.      * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
  76.      * @var string
  77.      * @access private
  78.      */
  79.     protected $cipher_name_mcrypt = 'tripledes';
  80.  
  81.     /**
  82.      * Optimizing value while CFB-encrypting
  83.      *
  84.      * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
  85.      * @var int
  86.      * @access private
  87.      */
  88.     protected $cfb_init_len = 750;
  89.  
  90.     /**
  91.      * max possible size of $key
  92.      *
  93.      * @see self::setKey()
  94.      * @see \phpseclib3\Crypt\DES::setKey()
  95.      * @var string
  96.      * @access private
  97.      */
  98.     protected $key_length_max = 24;
  99.  
  100.     /**
  101.      * Internal flag whether using self::MODE_3CBC or not
  102.      *
  103.      * @var bool
  104.      * @access private
  105.      */
  106.     private $mode_3cbc;
  107.  
  108.     /**
  109.      * The \phpseclib3\Crypt\DES objects
  110.      *
  111.      * Used only if $mode_3cbc === true
  112.      *
  113.      * @var array
  114.      * @access private
  115.      */
  116.     private $des;
  117.  
  118.     /**
  119.      * Default Constructor.
  120.      *
  121.      * Determines whether or not the mcrypt or OpenSSL extensions should be used.
  122.      *
  123.      * $mode could be:
  124.      *
  125.      * - ecb
  126.      *
  127.      * - cbc
  128.      *
  129.      * - ctr
  130.      *
  131.      * - cfb
  132.      *
  133.      * - ofb
  134.      *
  135.      * - 3cbc
  136.      *
  137.      * - cbc3 (same as cbc)
  138.      *
  139.      * @see \phpseclib3\Crypt\DES::__construct()
  140.      * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
  141.      * @param string $mode
  142.      * @access public
  143.      */
  144.     public function __construct($mode)
  145.     {
  146.         switch (strtolower($mode)) {
  147.             // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
  148.             // and additional flag us internally as 3CBC
  149.             case '3cbc':
  150.                 parent::__construct('cbc');
  151.                 $this->mode_3cbc = true;
  152.  
  153.                 // This three $des'es will do the 3CBC work (if $key > 64bits)
  154.                 $this->des = [
  155.                     new DES('cbc'),
  156.                     new DES('cbc'),
  157.                     new DES('cbc'),
  158.                 ];
  159.  
  160.                 // we're going to be doing the padding, ourselves, so disable it in the \phpseclib3\Crypt\DES objects
  161.                 $this->des[0]->disablePadding();
  162.                 $this->des[1]->disablePadding();
  163.                 $this->des[2]->disablePadding();
  164.                 break;
  165.             case 'cbc3':
  166.                 $mode = 'cbc';
  167.                 // fall-through
  168.             // If not 3CBC, we init as usual
  169.             default:
  170.                 parent::__construct($mode);
  171.  
  172.                 if ($this->mode == self::MODE_STREAM) {
  173.                     throw new BadModeException('Block ciphers cannot be ran in stream mode');
  174.                 }
  175.         }
  176.     }
  177.  
  178.     /**
  179.      * Test for engine validity
  180.      *
  181.      * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
  182.      *
  183.      * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
  184.      * @param int $engine
  185.      * @access protected
  186.      * @return bool
  187.      */
  188.     protected function isValidEngineHelper($engine)
  189.     {
  190.         if ($engine == self::ENGINE_OPENSSL) {
  191.             $this->cipher_name_openssl_ecb = 'des-ede3';
  192.             $mode = $this->openssl_translate_mode();
  193.             $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
  194.         }
  195.  
  196.         return parent::isValidEngineHelper($engine);
  197.     }
  198.  
  199.     /**
  200.      * Sets the initialization vector.
  201.      *
  202.      * SetIV is not required when \phpseclib3\Crypt\Common\SymmetricKey::MODE_ECB is being used.
  203.      *
  204.      * @see \phpseclib3\Crypt\Common\SymmetricKey::setIV()
  205.      * @access public
  206.      * @param string $iv
  207.      */
  208.     public function setIV($iv)
  209.     {
  210.         parent::setIV($iv);
  211.         if ($this->mode_3cbc) {
  212.             $this->des[0]->setIV($iv);
  213.             $this->des[1]->setIV($iv);
  214.             $this->des[2]->setIV($iv);
  215.         }
  216.     }
  217.  
  218.     /**
  219.      * Sets the key length.
  220.      *
  221.      * Valid key lengths are 128 and 192 bits.
  222.      *
  223.      * If you want to use a 64-bit key use DES.php
  224.      *
  225.      * @see \phpseclib3\Crypt\Common\SymmetricKey:setKeyLength()
  226.      * @access public
  227.      * @throws \LengthException if the key length is invalid
  228.      * @param int $length
  229.      */
  230.     public function setKeyLength($length)
  231.     {
  232.         switch ($length) {
  233.             case 128:
  234.             case 192:
  235.                 break;
  236.             default:
  237.                 throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported');
  238.         }
  239.  
  240.         parent::setKeyLength($length);
  241.     }
  242.  
  243.     /**
  244.      * Sets the key.
  245.      *
  246.      * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys.
  247.      *
  248.      * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
  249.      *
  250.      * @access public
  251.      * @see \phpseclib3\Crypt\DES::setKey()
  252.      * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
  253.      * @throws \LengthException if the key length is invalid
  254.      * @param string $key
  255.      */
  256.     public function setKey($key)
  257.     {
  258.         if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
  259.             throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
  260.         }
  261.  
  262.         switch (strlen($key)) {
  263.             case 16:
  264.                 $key .= substr($key, 0, 8);
  265.                 break;
  266.             case 24:
  267.                 break;
  268.             default:
  269.                 throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported');
  270.         }
  271.  
  272.         // copied from self::setKey()
  273.         $this->key = $key;
  274.         $this->key_length = strlen($key);
  275.         $this->changed = $this->nonIVChanged = true;
  276.         $this->setEngine();
  277.  
  278.         if ($this->mode_3cbc) {
  279.             $this->des[0]->setKey(substr($key, 0, 8));
  280.             $this->des[1]->setKey(substr($key, 8, 8));
  281.             $this->des[2]->setKey(substr($key, 16, 8));
  282.         }
  283.     }
  284.  
  285.     /**
  286.      * Encrypts a message.
  287.      *
  288.      * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
  289.      * @access public
  290.      * @param string $plaintext
  291.      * @return string $cipertext
  292.      */
  293.     public function encrypt($plaintext)
  294.     {
  295.         // parent::en/decrypt() is able to do all the work for all modes and keylengths,
  296.         // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
  297.  
  298.         // if the key is smaller then 8, do what we'd normally do
  299.         if ($this->mode_3cbc && strlen($this->key) > 8) {
  300.             return $this->des[2]->encrypt(
  301.                 $this->des[1]->decrypt(
  302.                     $this->des[0]->encrypt(
  303.                         $this->pad($plaintext)
  304.                     )
  305.                 )
  306.             );
  307.         }
  308.  
  309.         return parent::encrypt($plaintext);
  310.     }
  311.  
  312.     /**
  313.      * Decrypts a message.
  314.      *
  315.      * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
  316.      * @access public
  317.      * @param string $ciphertext
  318.      * @return string $plaintext
  319.      */
  320.     public function decrypt($ciphertext)
  321.     {
  322.         if ($this->mode_3cbc && strlen($this->key) > 8) {
  323.             return $this->unpad(
  324.                 $this->des[0]->decrypt(
  325.                     $this->des[1]->encrypt(
  326.                         $this->des[2]->decrypt(
  327.                             str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
  328.                         )
  329.                     )
  330.                 )
  331.             );
  332.         }
  333.  
  334.         return parent::decrypt($ciphertext);
  335.     }
  336.  
  337.     /**
  338.      * Treat consecutive "packets" as if they are a continuous buffer.
  339.      *
  340.      * Say you have a 16-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
  341.      * will yield different outputs:
  342.      *
  343.      * <code>
  344.      *    echo $des->encrypt(substr($plaintext, 0, 8));
  345.      *    echo $des->encrypt(substr($plaintext, 8, 8));
  346.      * </code>
  347.      * <code>
  348.      *    echo $des->encrypt($plaintext);
  349.      * </code>
  350.      *
  351.      * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
  352.      * another, as demonstrated with the following:
  353.      *
  354.      * <code>
  355.      *    $des->encrypt(substr($plaintext, 0, 8));
  356.      *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
  357.      * </code>
  358.      * <code>
  359.      *    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
  360.      * </code>
  361.      *
  362.      * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
  363.      * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
  364.      * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
  365.      *
  366.      * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\DES() object changes after each
  367.      * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
  368.      * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
  369.      * however, they are also less intuitive and more likely to cause you problems.
  370.      *
  371.      * @see \phpseclib3\Crypt\Common\SymmetricKey::enableContinuousBuffer()
  372.      * @see self::disableContinuousBuffer()
  373.      * @access public
  374.      */
  375.     public function enableContinuousBuffer()
  376.     {
  377.         parent::enableContinuousBuffer();
  378.         if ($this->mode_3cbc) {
  379.             $this->des[0]->enableContinuousBuffer();
  380.             $this->des[1]->enableContinuousBuffer();
  381.             $this->des[2]->enableContinuousBuffer();
  382.         }
  383.     }
  384.  
  385.     /**
  386.      * Treat consecutive packets as if they are a discontinuous buffer.
  387.      *
  388.      * The default behavior.
  389.      *
  390.      * @see \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer()
  391.      * @see self::enableContinuousBuffer()
  392.      * @access public
  393.      */
  394.     public function disableContinuousBuffer()
  395.     {
  396.         parent::disableContinuousBuffer();
  397.         if ($this->mode_3cbc) {
  398.             $this->des[0]->disableContinuousBuffer();
  399.             $this->des[1]->disableContinuousBuffer();
  400.             $this->des[2]->disableContinuousBuffer();
  401.         }
  402.     }
  403.  
  404.     /**
  405.      * Creates the key schedule
  406.      *
  407.      * @see \phpseclib3\Crypt\DES::setupKey()
  408.      * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
  409.      * @access private
  410.      */
  411.     protected function setupKey()
  412.     {
  413.         switch (true) {
  414.             // if $key <= 64bits we configure our internal pure-php cipher engine
  415.             // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
  416.             case strlen($this->key) <= 8:
  417.                 $this->des_rounds = 1;
  418.                 break;
  419.  
  420.             // otherwise, if $key > 64bits, we configure our engine to work as 3DES.
  421.             default:
  422.                 $this->des_rounds = 3;
  423.  
  424.                 // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
  425.                 if ($this->mode_3cbc) {
  426.                     $this->des[0]->setupKey();
  427.                     $this->des[1]->setupKey();
  428.                     $this->des[2]->setupKey();
  429.  
  430.                     // because $des[0-2] will, now, do all the work we can return here
  431.                     // not need unnecessary stress parent::setupKey() with our, now unused, $key.
  432.                     return;
  433.                 }
  434.         }
  435.         // setup our key
  436.         parent::setupKey();
  437.     }
  438.  
  439.     /**
  440.      * Sets the internal crypt engine
  441.      *
  442.      * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
  443.      * @see \phpseclib3\Crypt\Common\SymmetricKey::setPreferredEngine()
  444.      * @param int $engine
  445.      * @access public
  446.      */
  447.     public function setPreferredEngine($engine)
  448.     {
  449.         if ($this->mode_3cbc) {
  450.             $this->des[0]->setPreferredEngine($engine);
  451.             $this->des[1]->setPreferredEngine($engine);
  452.             $this->des[2]->setPreferredEngine($engine);
  453.         }
  454.  
  455.         parent::setPreferredEngine($engine);
  456.     }
  457. }
  458.