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

/src/Joomla/Crypt/Crypt.php

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