TripleDES.php 14 KB

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