PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/crypt/crypt.php

http://github.com/joomla/joomla-platform
PHP | 246 lines | 111 code | 28 blank | 107 comment | 15 complexity | c07b17a96f611a1a1625a6330bae76ac MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Crypt
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * JCrypt is a Joomla Platform class for handling basic encryption/decryption of data.
  12. *
  13. * @package Joomla.Platform
  14. * @subpackage Crypt
  15. * @since 12.1
  16. */
  17. class JCrypt
  18. {
  19. /**
  20. * @var JCryptCipher The encryption cipher object.
  21. * @since 12.1
  22. */
  23. private $_cipher;
  24. /**
  25. * @var JCryptKey The encryption key[/pair)].
  26. * @since 12.1
  27. */
  28. private $_key;
  29. /**
  30. * Object Constructor takes an optional key to be used for encryption/decryption. If no key is given then the
  31. * secret word from the configuration object is used.
  32. *
  33. * @param JCryptCipher $cipher The encryption cipher object.
  34. * @param JCryptKey $key The encryption key[/pair)].
  35. *
  36. * @since 12.1
  37. */
  38. public function __construct(JCryptCipher $cipher = null, JCryptKey $key = null)
  39. {
  40. // Set the encryption key[/pair)].
  41. $this->_key = $key;
  42. // Set the encryption cipher.
  43. $this->_cipher = isset($cipher) ? $cipher : new JCryptCipherSimple;
  44. }
  45. /**
  46. * Method to decrypt a data string.
  47. *
  48. * @param string $data The encrypted string to decrypt.
  49. *
  50. * @return string The decrypted data string.
  51. *
  52. * @since 12.1
  53. */
  54. public function decrypt($data)
  55. {
  56. return $this->_cipher->decrypt($data, $this->_key);
  57. }
  58. /**
  59. * Method to encrypt a data string.
  60. *
  61. * @param string $data The data string to encrypt.
  62. *
  63. * @return string The encrypted data string.
  64. *
  65. * @since 12.1
  66. */
  67. public function encrypt($data)
  68. {
  69. return $this->_cipher->encrypt($data, $this->_key);
  70. }
  71. /**
  72. * Method to generate a new encryption key[/pair] object.
  73. *
  74. * @param array $options Key generation options.
  75. *
  76. * @return JCryptKey
  77. *
  78. * @since 12.1
  79. */
  80. public function generateKey(array $options = array())
  81. {
  82. return $this->_cipher->generateKey($options);
  83. }
  84. /**
  85. * Method to set the encryption key[/pair] object.
  86. *
  87. * @param JCryptKey $key The key object to set.
  88. *
  89. * @return JCrypt
  90. *
  91. * @since 12.1
  92. */
  93. public function setKey(JCryptKey $key)
  94. {
  95. $this->_key = $key;
  96. return $this;
  97. }
  98. /**
  99. * Generate random bytes.
  100. *
  101. * @param integer $length Length of the random data to generate
  102. *
  103. * @return string Random binary data
  104. *
  105. * @since 12.1
  106. */
  107. public static function genRandomBytes($length = 16)
  108. {
  109. $sslStr = '';
  110. /*
  111. * if a secure randomness generator exists and we don't
  112. * have a buggy PHP version use it.
  113. */
  114. if (function_exists('openssl_random_pseudo_bytes')
  115. && (version_compare(PHP_VERSION, '5.3.4') >= 0 || IS_WIN))
  116. {
  117. $sslStr = openssl_random_pseudo_bytes($length, $strong);
  118. if ($strong)
  119. {
  120. return $sslStr;
  121. }
  122. }
  123. /*
  124. * Collect any entropy available in the system along with a number
  125. * of time measurements of operating system randomness.
  126. */
  127. $bitsPerRound = 2;
  128. $maxTimeMicro = 400;
  129. $shaHashLength = 20;
  130. $randomStr = '';
  131. $total = $length;
  132. // Check if we can use /dev/urandom.
  133. $urandom = false;
  134. $handle = null;
  135. // This is PHP 5.3.3 and up
  136. if (function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom'))
  137. {
  138. $handle = @fopen('/dev/urandom', 'rb');
  139. if ($handle)
  140. {
  141. $urandom = true;
  142. }
  143. }
  144. while ($length > strlen($randomStr))
  145. {
  146. $bytes = ($total > $shaHashLength)? $shaHashLength : $total;
  147. $total -= $bytes;
  148. /*
  149. * Collect any entropy available from the PHP system and filesystem.
  150. * If we have ssl data that isn't strong, we use it once.
  151. */
  152. $entropy = rand() . uniqid(mt_rand(), true) . $sslStr;
  153. $entropy .= implode('', @fstat(fopen(__FILE__, 'r')));
  154. $entropy .= memory_get_usage();
  155. $sslStr = '';
  156. if ($urandom)
  157. {
  158. stream_set_read_buffer($handle, 0);
  159. $entropy .= @fread($handle, $bytes);
  160. }
  161. else
  162. {
  163. /*
  164. * There is no external source of entropy so we repeat calls
  165. * to mt_rand until we are assured there's real randomness in
  166. * the result.
  167. *
  168. * Measure the time that the operations will take on average.
  169. */
  170. $samples = 3;
  171. $duration = 0;
  172. for ($pass = 0; $pass < $samples; ++$pass)
  173. {
  174. $microStart = microtime(true) * 1000000;
  175. $hash = sha1(mt_rand(), true);
  176. for ($count = 0; $count < 50; ++$count)
  177. {
  178. $hash = sha1($hash, true);
  179. }
  180. $microEnd = microtime(true) * 1000000;
  181. $entropy .= $microStart . $microEnd;
  182. if ($microStart >= $microEnd)
  183. {
  184. $microEnd += 1000000;
  185. }
  186. $duration += $microEnd - $microStart;
  187. }
  188. $duration = $duration / $samples;
  189. /*
  190. * Based on the average time, determine the total rounds so that
  191. * the total running time is bounded to a reasonable number.
  192. */
  193. $rounds = (int) (($maxTimeMicro / $duration) * 50);
  194. /*
  195. * Take additional measurements. On average we can expect
  196. * at least $bitsPerRound bits of entropy from each measurement.
  197. */
  198. $iter = $bytes * (int) ceil(8 / $bitsPerRound);
  199. for ($pass = 0; $pass < $iter; ++$pass)
  200. {
  201. $microStart = microtime(true);
  202. $hash = sha1(mt_rand(), true);
  203. for ($count = 0; $count < $rounds; ++$count)
  204. {
  205. $hash = sha1($hash, true);
  206. }
  207. $entropy .= $microStart . microtime(true);
  208. }
  209. }
  210. $randomStr .= sha1($entropy, true);
  211. }
  212. if ($urandom)
  213. {
  214. @fclose($handle);
  215. }
  216. return substr($randomStr, 0, $length);
  217. }
  218. }