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