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