PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/system/libraries/Encrypt.php

http://github.com/prashants/webzash
PHP | 484 lines | 203 code | 69 blank | 212 comment | 29 complexity | af5e459913d4be8dd667e25400636655 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 4.3.2 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author ExpressionEngine Dev Team
  9. * @copyright Copyright (c) 2008 - 2010, EllisLab, Inc.
  10. * @license http://codeigniter.com/user_guide/license.html
  11. * @link http://codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * CodeIgniter Encryption Class
  18. *
  19. * Provides two-way keyed encoding using XOR Hashing and Mcrypt
  20. *
  21. * @package CodeIgniter
  22. * @subpackage Libraries
  23. * @category Libraries
  24. * @author ExpressionEngine Dev Team
  25. * @link http://codeigniter.com/user_guide/libraries/encryption.html
  26. */
  27. class CI_Encrypt {
  28. var $CI;
  29. var $encryption_key = '';
  30. var $_hash_type = 'sha1';
  31. var $_mcrypt_exists = FALSE;
  32. var $_mcrypt_cipher;
  33. var $_mcrypt_mode;
  34. /**
  35. * Constructor
  36. *
  37. * Simply determines whether the mcrypt library exists.
  38. *
  39. */
  40. function CI_Encrypt()
  41. {
  42. $this->CI =& get_instance();
  43. $this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
  44. log_message('debug', "Encrypt Class Initialized");
  45. }
  46. // --------------------------------------------------------------------
  47. /**
  48. * Fetch the encryption key
  49. *
  50. * Returns it as MD5 in order to have an exact-length 128 bit key.
  51. * Mcrypt is sensitive to keys that are not the correct length
  52. *
  53. * @access public
  54. * @param string
  55. * @return string
  56. */
  57. function get_key($key = '')
  58. {
  59. if ($key == '')
  60. {
  61. if ($this->encryption_key != '')
  62. {
  63. return $this->encryption_key;
  64. }
  65. $CI =& get_instance();
  66. $key = $CI->config->item('encryption_key');
  67. if ($key === FALSE)
  68. {
  69. show_error('In order to use the encryption class requires that you set an encryption key in your config file.');
  70. }
  71. }
  72. return md5($key);
  73. }
  74. // --------------------------------------------------------------------
  75. /**
  76. * Set the encryption key
  77. *
  78. * @access public
  79. * @param string
  80. * @return void
  81. */
  82. function set_key($key = '')
  83. {
  84. $this->encryption_key = $key;
  85. }
  86. // --------------------------------------------------------------------
  87. /**
  88. * Encode
  89. *
  90. * Encodes the message string using bitwise XOR encoding.
  91. * The key is combined with a random hash, and then it
  92. * too gets converted using XOR. The whole thing is then run
  93. * through mcrypt (if supported) using the randomized key.
  94. * The end result is a double-encrypted message string
  95. * that is randomized with each call to this function,
  96. * even if the supplied message and key are the same.
  97. *
  98. * @access public
  99. * @param string the string to encode
  100. * @param string the key
  101. * @return string
  102. */
  103. function encode($string, $key = '')
  104. {
  105. $key = $this->get_key($key);
  106. $enc = $this->_xor_encode($string, $key);
  107. if ($this->_mcrypt_exists === TRUE)
  108. {
  109. $enc = $this->mcrypt_encode($enc, $key);
  110. }
  111. return base64_encode($enc);
  112. }
  113. // --------------------------------------------------------------------
  114. /**
  115. * Decode
  116. *
  117. * Reverses the above process
  118. *
  119. * @access public
  120. * @param string
  121. * @param string
  122. * @return string
  123. */
  124. function decode($string, $key = '')
  125. {
  126. $key = $this->get_key($key);
  127. if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string))
  128. {
  129. return FALSE;
  130. }
  131. $dec = base64_decode($string);
  132. if ($this->_mcrypt_exists === TRUE)
  133. {
  134. if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE)
  135. {
  136. return FALSE;
  137. }
  138. }
  139. return $this->_xor_decode($dec, $key);
  140. }
  141. // --------------------------------------------------------------------
  142. /**
  143. * XOR Encode
  144. *
  145. * Takes a plain-text string and key as input and generates an
  146. * encoded bit-string using XOR
  147. *
  148. * @access private
  149. * @param string
  150. * @param string
  151. * @return string
  152. */
  153. function _xor_encode($string, $key)
  154. {
  155. $rand = '';
  156. while (strlen($rand) < 32)
  157. {
  158. $rand .= mt_rand(0, mt_getrandmax());
  159. }
  160. $rand = $this->hash($rand);
  161. $enc = '';
  162. for ($i = 0; $i < strlen($string); $i++)
  163. {
  164. $enc .= substr($rand, ($i % strlen($rand)), 1).(substr($rand, ($i % strlen($rand)), 1) ^ substr($string, $i, 1));
  165. }
  166. return $this->_xor_merge($enc, $key);
  167. }
  168. // --------------------------------------------------------------------
  169. /**
  170. * XOR Decode
  171. *
  172. * Takes an encoded string and key as input and generates the
  173. * plain-text original message
  174. *
  175. * @access private
  176. * @param string
  177. * @param string
  178. * @return string
  179. */
  180. function _xor_decode($string, $key)
  181. {
  182. $string = $this->_xor_merge($string, $key);
  183. $dec = '';
  184. for ($i = 0; $i < strlen($string); $i++)
  185. {
  186. $dec .= (substr($string, $i++, 1) ^ substr($string, $i, 1));
  187. }
  188. return $dec;
  189. }
  190. // --------------------------------------------------------------------
  191. /**
  192. * XOR key + string Combiner
  193. *
  194. * Takes a string and key as input and computes the difference using XOR
  195. *
  196. * @access private
  197. * @param string
  198. * @param string
  199. * @return string
  200. */
  201. function _xor_merge($string, $key)
  202. {
  203. $hash = $this->hash($key);
  204. $str = '';
  205. for ($i = 0; $i < strlen($string); $i++)
  206. {
  207. $str .= substr($string, $i, 1) ^ substr($hash, ($i % strlen($hash)), 1);
  208. }
  209. return $str;
  210. }
  211. // --------------------------------------------------------------------
  212. /**
  213. * Encrypt using Mcrypt
  214. *
  215. * @access public
  216. * @param string
  217. * @param string
  218. * @return string
  219. */
  220. function mcrypt_encode($data, $key)
  221. {
  222. $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
  223. $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
  224. return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);
  225. }
  226. // --------------------------------------------------------------------
  227. /**
  228. * Decrypt using Mcrypt
  229. *
  230. * @access public
  231. * @param string
  232. * @param string
  233. * @return string
  234. */
  235. function mcrypt_decode($data, $key)
  236. {
  237. $data = $this->_remove_cipher_noise($data, $key);
  238. $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
  239. if ($init_size > strlen($data))
  240. {
  241. return FALSE;
  242. }
  243. $init_vect = substr($data, 0, $init_size);
  244. $data = substr($data, $init_size);
  245. return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0");
  246. }
  247. // --------------------------------------------------------------------
  248. /**
  249. * Adds permuted noise to the IV + encrypted data to protect
  250. * against Man-in-the-middle attacks on CBC mode ciphers
  251. * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV
  252. *
  253. * Function description
  254. *
  255. * @access private
  256. * @param string
  257. * @param string
  258. * @return string
  259. */
  260. function _add_cipher_noise($data, $key)
  261. {
  262. $keyhash = $this->hash($key);
  263. $keylen = strlen($keyhash);
  264. $str = '';
  265. for ($i = 0, $j = 0, $len = strlen($data); $i < $len; ++$i, ++$j)
  266. {
  267. if ($j >= $keylen)
  268. {
  269. $j = 0;
  270. }
  271. $str .= chr((ord($data[$i]) + ord($keyhash[$j])) % 256);
  272. }
  273. return $str;
  274. }
  275. // --------------------------------------------------------------------
  276. /**
  277. * Removes permuted noise from the IV + encrypted data, reversing
  278. * _add_cipher_noise()
  279. *
  280. * Function description
  281. *
  282. * @access public
  283. * @param type
  284. * @return type
  285. */
  286. function _remove_cipher_noise($data, $key)
  287. {
  288. $keyhash = $this->hash($key);
  289. $keylen = strlen($keyhash);
  290. $str = '';
  291. for ($i = 0, $j = 0, $len = strlen($data); $i < $len; ++$i, ++$j)
  292. {
  293. if ($j >= $keylen)
  294. {
  295. $j = 0;
  296. }
  297. $temp = ord($data[$i]) - ord($keyhash[$j]);
  298. if ($temp < 0)
  299. {
  300. $temp = $temp + 256;
  301. }
  302. $str .= chr($temp);
  303. }
  304. return $str;
  305. }
  306. // --------------------------------------------------------------------
  307. /**
  308. * Set the Mcrypt Cipher
  309. *
  310. * @access public
  311. * @param constant
  312. * @return string
  313. */
  314. function set_cipher($cipher)
  315. {
  316. $this->_mcrypt_cipher = $cipher;
  317. }
  318. // --------------------------------------------------------------------
  319. /**
  320. * Set the Mcrypt Mode
  321. *
  322. * @access public
  323. * @param constant
  324. * @return string
  325. */
  326. function set_mode($mode)
  327. {
  328. $this->_mcrypt_mode = $mode;
  329. }
  330. // --------------------------------------------------------------------
  331. /**
  332. * Get Mcrypt cipher Value
  333. *
  334. * @access private
  335. * @return string
  336. */
  337. function _get_cipher()
  338. {
  339. if ($this->_mcrypt_cipher == '')
  340. {
  341. $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
  342. }
  343. return $this->_mcrypt_cipher;
  344. }
  345. // --------------------------------------------------------------------
  346. /**
  347. * Get Mcrypt Mode Value
  348. *
  349. * @access private
  350. * @return string
  351. */
  352. function _get_mode()
  353. {
  354. if ($this->_mcrypt_mode == '')
  355. {
  356. $this->_mcrypt_mode = MCRYPT_MODE_ECB;
  357. }
  358. return $this->_mcrypt_mode;
  359. }
  360. // --------------------------------------------------------------------
  361. /**
  362. * Set the Hash type
  363. *
  364. * @access public
  365. * @param string
  366. * @return string
  367. */
  368. function set_hash($type = 'sha1')
  369. {
  370. $this->_hash_type = ($type != 'sha1' AND $type != 'md5') ? 'sha1' : $type;
  371. }
  372. // --------------------------------------------------------------------
  373. /**
  374. * Hash encode a string
  375. *
  376. * @access public
  377. * @param string
  378. * @return string
  379. */
  380. function hash($str)
  381. {
  382. return ($this->_hash_type == 'sha1') ? $this->sha1($str) : md5($str);
  383. }
  384. // --------------------------------------------------------------------
  385. /**
  386. * Generate an SHA1 Hash
  387. *
  388. * @access public
  389. * @param string
  390. * @return string
  391. */
  392. function sha1($str)
  393. {
  394. if ( ! function_exists('sha1'))
  395. {
  396. if ( ! function_exists('mhash'))
  397. {
  398. require_once(BASEPATH.'libraries/Sha1'.EXT);
  399. $SH = new CI_SHA;
  400. return $SH->generate($str);
  401. }
  402. else
  403. {
  404. return bin2hex(mhash(MHASH_SHA1, $str));
  405. }
  406. }
  407. else
  408. {
  409. return sha1($str);
  410. }
  411. }
  412. }
  413. // END CI_Encrypt class
  414. /* End of file Encrypt.php */
  415. /* Location: ./system/libraries/Encrypt.php */