PageRenderTime 56ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/RandomLib/Source/MicroTime.php

https://github.com/ezimuel/RandomLib
PHP | 122 lines | 51 code | 10 blank | 61 comment | 6 complexity | 53b15878c4358c4984ba943434920ed6 MD5 | raw file
  1. <?php
  2. /**
  3. * The Microtime Random Number Source
  4. *
  5. * This uses the current micro-second (looped several times) for a **very** weak
  6. * random number source. This is only useful when combined with several other
  7. * stronger sources
  8. *
  9. * PHP version 5.3
  10. *
  11. * @category PHPCryptLib
  12. * @package Random
  13. * @subpackage Source
  14. * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
  15. * @copyright 2011 The Authors
  16. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  17. * @version Build @@version@@
  18. */
  19. namespace RandomLib\Source;
  20. use SecurityLib\Strength;
  21. /**
  22. * The Microtime Random Number Source
  23. *
  24. * This uses the current micro-second (looped several times) for a **very** weak
  25. * random number source. This is only useful when combined with several other
  26. * stronger sources
  27. *
  28. * @category PHPCryptLib
  29. * @package Random
  30. * @subpackage Source
  31. * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
  32. * @codeCoverageIgnore
  33. */
  34. final class MicroTime implements \RandomLib\Source {
  35. /**
  36. * A static counter to ensure unique hashes and prevent state collisions
  37. * @var int A counter
  38. */
  39. private static $counter = null;
  40. /**
  41. * The current state of the random number generator.
  42. * @var string The state of the PRNG
  43. */
  44. private static $state = '';
  45. /**
  46. * Return an instance of Strength indicating the strength of the source
  47. *
  48. * @return Strength An instance of one of the strength classes
  49. */
  50. public static function getStrength() {
  51. return new Strength(Strength::VERYLOW);
  52. }
  53. public function __construct() {
  54. $state = self::$state;
  55. if (function_exists('posix_times')) {
  56. $state .= serialize(posix_times());
  57. }
  58. if (function_exists('zend_thread_id')) {
  59. $state .= zend_thread_id();
  60. }
  61. $state .= getmypid() . memory_get_usage();
  62. $state .= serialize($_ENV);
  63. $state .= serialize($_SERVER);
  64. $state .= serialize(debug_backtrace(false));
  65. self::$state = hash('sha512', $state, true);
  66. if (is_null(self::$counter)) {
  67. self::$counter = bindec(substr(self::$state, 0, 4));
  68. $seed = $this->generate(strlen(dechex(PHP_INT_MAX)));
  69. self::$counter = bindec($seed);
  70. }
  71. }
  72. /**
  73. * Generate a random string of the specified size
  74. *
  75. * @param int $size The size of the requested random string
  76. *
  77. * @return string A string of the requested size
  78. */
  79. public function generate($size) {
  80. $result = '';
  81. $seed = microtime() . memory_get_usage();
  82. self::$state = hash('sha512', self::$state . $seed, true);
  83. /**
  84. * Make the generated randomness a bit better by forcing a GC run which
  85. * should complete in a indeterminate amount of time, hence improving
  86. * the strength of the randomness a bit. It's still not crypto-safe,
  87. * but at least it's more difficult to predict.
  88. */
  89. gc_collect_cycles();
  90. for ($i = 0; $i < $size; $i += 8) {
  91. $seed = self::$state .
  92. microtime() .
  93. pack('Ni', $i, self::counter());
  94. self::$state = hash('sha512', $seed, true);
  95. /**
  96. * We only use the first 8 bytes here to prevent exposing the state
  97. * in its entirety, which could potentially expose other random
  98. * generations in the future (in the same process)...
  99. */
  100. $result .= substr(self::$state, 0, 8);
  101. }
  102. return substr($result, 0, $size);
  103. }
  104. private static function counter() {
  105. if (self::$counter >= PHP_INT_MAX) {
  106. self::$counter = -1 * PHP_INT_MAX - 1;
  107. } else {
  108. self::$counter++;
  109. }
  110. return self::$counter;
  111. }
  112. }