PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/fuel/core/classes/crypt.php

https://github.com/ifaour/fuel
PHP | 328 lines | 166 code | 43 blank | 119 comment | 22 complexity | 287b64e9a25db0ff57720ecf935b1ec6 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. <?php
  2. /**
  3. * Fuel
  4. *
  5. * Fuel is a fast, lightweight, community driven PHP5 framework.
  6. *
  7. * @package Fuel
  8. * @version 1.0
  9. * @author Fuel Development Team
  10. * @license MIT License
  11. * @copyright 2010 - 2011 Fuel Development Team
  12. * @link http://fuelphp.com
  13. */
  14. namespace Fuel\Core;
  15. /**
  16. * Crypt Class
  17. *
  18. * @package Fuel
  19. * @category Core
  20. * @author Harro "WanWizard" Verton
  21. * @link http://fuelphp.com/docs/classes/crypt.html
  22. */
  23. class Crypt {
  24. /**
  25. * @var boolean idicator for the usage of mcrypt
  26. */
  27. public static $use_mcrypt = true;
  28. /**
  29. * @var string Magic salt to use as encryption key
  30. */
  31. public static $salt = 'sup3rs3Cr3tk3y564';
  32. /**
  33. * @var boolean idicator for the availability of mcrypt
  34. */
  35. protected static $have_mcrypt = false;
  36. /**
  37. * @var int default mcrypt cipher to use
  38. */
  39. protected static $mcrypt_cipher = 'rijndael-256';
  40. /**
  41. * @var int default mcrypt mode to use
  42. */
  43. protected static $mcrypt_mode = 'cbc';
  44. // --------------------------------------------------------------------
  45. /*
  46. * initialisation and auto configuration
  47. */
  48. public static function _init()
  49. {
  50. // check we we have the mcrypt library available
  51. static::$have_mcrypt = function_exists('mcrypt_encrypt');
  52. // load the config
  53. $config = \Config::load('crypt', true);
  54. // update the defaults with the configed values
  55. foreach($config as $key => $value)
  56. {
  57. isset(static::${$key}) && static::${$key} = $value;
  58. }
  59. }
  60. // --------------------------------------------------------------------
  61. /*
  62. * set a configuration value
  63. *
  64. * @param string name of the configuration key
  65. * @param string value to be set
  66. * @access public
  67. * @return void
  68. */
  69. public static function set($name = false, $value = null)
  70. {
  71. $name && isset(static::${$name}) && static::${$name} = $value;
  72. }
  73. // --------------------------------------------------------------------
  74. /*
  75. * get a configuration value
  76. *
  77. * @param string name of the configuration key
  78. * @access public
  79. * @return string the configuration key value, or false if the key is invalid
  80. */
  81. public static function get($name = false)
  82. {
  83. return $name && isset(static::${$name}) ? static::${$name} : false;
  84. }
  85. // --------------------------------------------------------------------
  86. /*
  87. * encrypt a string value, optionally with a custom salt
  88. *
  89. * @param string value to encrypt
  90. * @param string optional salt to be used for this encryption
  91. * @access public
  92. * @return string encrypted value
  93. */
  94. public static function encode($value, $salt = false)
  95. {
  96. // if no salt is given, use the default salt
  97. if ($salt === false)
  98. {
  99. $salt = static::$salt;
  100. }
  101. // check if we have mcrypt available, and we want to use it
  102. if (static::$have_mcrypt && static::$use_mcrypt)
  103. {
  104. // encrypt using mcrypt
  105. $iv_size = mcrypt_get_iv_size(static::$mcrypt_cipher, static::$mcrypt_mode);
  106. $iv_vector = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  107. $value = '1:'.static::_add_cipher_noise($iv_vector.mcrypt_encrypt(static::$mcrypt_cipher, $salt, $value, static::$mcrypt_mode, $iv_vector), $salt);
  108. }
  109. else
  110. {
  111. $keys = static::_crypt_key($salt);
  112. for($i = 0; $i < strlen($value); $i++){
  113. $id = $i % count($keys);
  114. $ord = ord($value{$i});
  115. $ord = $ord OR ord($keys[$id]);
  116. $id++;
  117. $ord = $ord AND ord($keys[$id]);
  118. $id++;
  119. $ord = $ord XOR ord($keys[$id]);
  120. $id++;
  121. $ord = $ord + ord($keys[$id]);
  122. $value{$i} = chr($ord);
  123. }
  124. $value = '0:'.$value;
  125. }
  126. // make the encoding URL save
  127. return strtr(
  128. base64_encode($value),
  129. array(
  130. '+' => '.',
  131. '=' => '-',
  132. '/' => '~'
  133. )
  134. );
  135. }
  136. // --------------------------------------------------------------------
  137. /*
  138. * decrypt a string value, optionally with a custom salt
  139. *
  140. * the method automatically detects if mcrypt was used on encryption
  141. *
  142. * @param string value to decrypt
  143. * @param string optional salt to be used for this encryption
  144. * @access public
  145. * @return string encrypted value
  146. */
  147. public static function decode($value, $salt = false)
  148. {
  149. // if no salt is given, use the default salt
  150. if ($salt === false)
  151. {
  152. $salt = static::$salt;
  153. }
  154. // decode the value passed
  155. $value = base64_decode(strtr(
  156. $value,
  157. array(
  158. '.' => '+',
  159. '-' => '=',
  160. '~' => '/'
  161. )
  162. ));
  163. // check if we have mcrypt available, and the value was encrypted by mcrypt
  164. if (static::$have_mcrypt && substr($value,0,2) == '1:')
  165. {
  166. // decrypt using mcrypt
  167. $value = static::_remove_cipher_noise(substr($value,2), $salt);
  168. $iv_size = mcrypt_get_iv_size(static::$mcrypt_cipher, static::$mcrypt_mode);
  169. if ($iv_size > strlen($value))
  170. {
  171. return false;
  172. }
  173. $iv_vector = substr($value, 0, $iv_size);
  174. $value = substr($value, $iv_size);
  175. $value = rtrim(mcrypt_decrypt(static::$mcrypt_cipher, $salt, $value, static::$mcrypt_mode, $iv_vector), "\0");
  176. }
  177. else
  178. {
  179. // was the value encrypted using mcrypt
  180. if (substr($value,0,2) == '1:')
  181. {
  182. // houston, we have a problem!
  183. throw new \Exception('Encrypted string was encrypted using the PHP mcrypt library, which is not loaded on this system.');
  184. }
  185. $value = substr($value,2);
  186. $keys = static::_crypt_key($salt);
  187. for($i = 0; $i < strlen($value); $i++){
  188. $id = $i % count($keys);
  189. $ord = ord($value{$i});
  190. $ord = $ord XOR ord($keys[$id]);
  191. $id++;
  192. $ord = $ord AND ord($keys[$id]);
  193. $id++;
  194. $ord = $ord OR ord($keys[$id]);
  195. $id++;
  196. $ord = $ord - ord($keys[$id]);
  197. $value{$i} = chr($ord);
  198. }
  199. }
  200. return $value;
  201. }
  202. // --------------------------------------------------------------------
  203. /**
  204. * Adds permuted noise to the IV + encrypted data to protect
  205. * against Man-in-the-middle attacks on CBC mode ciphers
  206. * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV
  207. *
  208. * @param string
  209. * @param string
  210. * @access private
  211. * @return string
  212. */
  213. protected static function _add_cipher_noise($value, $salt)
  214. {
  215. $keyhash = sha1($salt);
  216. $keylen = strlen($keyhash);
  217. $str = '';
  218. for ($i = 0, $j = 0, $len = strlen($value); $i < $len; ++$i, ++$j)
  219. {
  220. if ($j >= $keylen)
  221. {
  222. $j = 0;
  223. }
  224. $str .= chr((ord($value[$i]) + ord($keyhash[$j])) % 256);
  225. }
  226. return $str;
  227. }
  228. // --------------------------------------------------------------------
  229. /**
  230. * Removes permuted noise from the IV + encrypted data, reversing
  231. * _add_cipher_noise()
  232. *
  233. * @param string
  234. * @param string
  235. * @access private
  236. * @return string
  237. */
  238. protected static function _remove_cipher_noise($value, $salt)
  239. {
  240. $keyhash = sha1($salt);
  241. $keylen = strlen($keyhash);
  242. $str = '';
  243. for ($i = 0, $j = 0, $len = strlen($value); $i < $len; ++$i, ++$j)
  244. {
  245. if ($j >= $keylen)
  246. {
  247. $j = 0;
  248. }
  249. $temp = ord($value[$i]) - ord($keyhash[$j]);
  250. if ($temp < 0)
  251. {
  252. $temp = $temp + 256;
  253. }
  254. $str .= chr($temp);
  255. }
  256. return $str;
  257. }
  258. // --------------------------------------------------------------------
  259. /**
  260. * generate a crypt key for non-mcrypt encryption
  261. *
  262. * @param string salt
  263. * @access private
  264. * @return array keys used for the encryption algorithm
  265. */
  266. protected static function _crypt_key($salt)
  267. {
  268. $keys = array();
  269. $c_key = base64_encode(sha1(md5($salt)));
  270. $c_key = substr($c_key, 0, round(ord($salt{0})/5));
  271. $c2_key = base64_encode(md5(sha1($salt)));
  272. $last = strlen($salt) - 1;
  273. $c2_key = substr($c2_key, 1, round(ord($salt{$last})/7));
  274. $c3_key = base64_encode(sha1(md5($c_key).md5($c2_key)));
  275. $mid = round($last/2);
  276. $c3_key = substr($c3_key, 1, round(ord($salt{$mid})/9));
  277. $c_key = $c_key.$c2_key.$c3_key;
  278. $c_key = base64_encode($c_key);
  279. for($i = 0; $i < strlen($c_key); $i++){
  280. $keys[] = $c_key[$i];
  281. }
  282. return $keys;
  283. }
  284. }
  285. /* End of file encrypt.php */