123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- <?php
- /*
- * The RandomLib library for securely generating random numbers and strings in PHP
- *
- * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
- * @copyright 2011 The Authors
- * @license http://www.opensource.org/licenses/mit-license.html MIT License
- * @version Build @@version@@
- */
- /**
- * The Random Factory
- *
- * Use this factory to instantiate random number generators, sources and mixers.
- *
- * PHP version 5.3
- *
- * @category PHPPasswordLib
- * @package Random
- *
- * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
- * @author Paragon Initiative Enterprises <security@paragonie.com>
- * @copyright 2011 The Authors
- * @license http://www.opensource.org/licenses/mit-license.html MIT License
- *
- * @version Build @@version@@
- */
- namespace RandomLib;
- use SecurityLib\Strength;
- /**
- * The Random Factory
- *
- * Use this factory to instantiate random number generators, sources and mixers.
- *
- * @category PHPPasswordLib
- * @package Random
- *
- * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
- * @author Paragon Initiative Enterprises <security@paragonie.com>
- */
- class Factory extends \SecurityLib\AbstractFactory
- {
- /**
- * @var array<int, Mixer> A list of available random number mixing strategies
- */
- protected $mixers = array();
- /**
- * @var array<int, Source> A list of available random number sources
- */
- protected $sources = array();
- /**
- * Build a new instance of the factory, loading core mixers and sources
- *
- * @return void
- */
- public function __construct()
- {
- $this->loadMixers();
- $this->loadSources();
- }
- /**
- * Get a generator for the requested strength
- *
- * @param Strength $strength The requested strength of the random number
- *
- * @throws \RuntimeException If an appropriate mixing strategy isn't found
- *
- * @return Generator The instantiated generator
- */
- public function getGenerator(\SecurityLib\Strength $strength)
- {
- $sources = $this->findSources($strength);
- $mixer = $this->findMixer($strength);
- return new Generator($sources, $mixer);
- }
- /**
- * Get a high strength random number generator
- *
- * High Strength keys should ONLY be used for generating extremely strong
- * cryptographic keys. Generating them is very resource intensive and may
- * take several minutes or more depending on the requested size.
- *
- * @return Generator The instantiated generator
- */
- public function getHighStrengthGenerator()
- {
- return $this->getGenerator(new Strength(Strength::HIGH));
- }
- /**
- * Get a low strength random number generator
- *
- * Low Strength should be used anywhere that random strings are needed in a
- * non-cryptographical setting. They are not strong enough to be used as
- * keys or salts. They are however useful for one-time use tokens.
- *
- * @return Generator The instantiated generator
- */
- public function getLowStrengthGenerator()
- {
- return $this->getGenerator(new Strength(Strength::LOW));
- }
- /**
- * Get a medium strength random number generator
- *
- * Medium Strength should be used for most needs of a cryptographic nature.
- * They are strong enough to be used as keys and salts. However, they do
- * take some time and resources to generate, so they should not be over-used
- *
- * @return Generator The instantiated generator
- */
- public function getMediumStrengthGenerator()
- {
- return $this->getGenerator(new Strength(Strength::MEDIUM));
- }
- /**
- * Get all loaded mixing strategies
- *
- * @return array<int, Mixer> An array of mixers
- */
- public function getMixers()
- {
- return $this->mixers;
- }
- /**
- * Get all loaded random number sources
- *
- * @return array<int, Source> An array of sources
- */
- public function getSources()
- {
- return $this->sources;
- }
- /**
- * Register a mixing strategy for this factory instance
- *
- * @param string $name The name of the stategy
- * @param string $class The class name of the implementation
- *
- * @return Factory $this The current factory instance
- */
- public function registerMixer($name, $class)
- {
- $this->registerType(
- 'mixers',
- __NAMESPACE__ . '\\Mixer',
- $name,
- $class
- );
- return $this;
- }
- /**
- * Register a random number source for this factory instance
- *
- * Note that this class must implement the Source interface
- *
- * @param string $name The name of the stategy
- * @param string $class The class name of the implementation
- *
- * @return Factory $this The current factory instance
- */
- public function registerSource($name, $class)
- {
- $this->registerType(
- 'sources',
- __NAMESPACE__ . '\\Source',
- $name,
- $class
- );
- return $this;
- }
- /**
- * Find a sources based upon the requested strength
- *
- * @param Strength $strength The strength mixer to find
- *
- * @throws \RuntimeException if a valid source cannot be found
- *
- * @return array<int, Source> The found source
- */
- protected function findSources(\SecurityLib\Strength $strength)
- {
- /** @var array<int, Source> $sources */
- $sources = array();
- foreach ($this->getSources() as $source) {
- if ($strength->compare($source::getStrength()) <= 0 && $source::isSupported()) {
- /** @var Source $obj */
- $obj = new $source();
- if ($obj instanceof Source) {
- $sources[] = $obj;
- }
- }
- }
- if (0 === count($sources)) {
- throw new \RuntimeException('Could not find sources');
- }
- return $sources;
- }
- /**
- * Find a mixer based upon the requested strength
- *
- * @param Strength $strength The strength mixer to find
- *
- * @throws \RuntimeException if a valid mixer cannot be found
- *
- * @return Mixer The found mixer
- */
- protected function findMixer(\SecurityLib\Strength $strength)
- {
- /** @var Mixer|null $newMixer */
- $newMixer = null;
- /** @var Mixer|null $fallback */
- $fallback = null;
- foreach ($this->getMixers() as $mixer) {
- if (!$mixer::test() || !$mixer::advisable()) {
- continue;
- }
- if ($strength->compare($mixer::getStrength()) == 0) {
- /** @var Mixer $newMixer */
- $newMixer = new $mixer();
- } elseif ($strength->compare($mixer::getStrength()) == 1) {
- /** @var Mixer $fallback */
- $fallback = new $mixer();
- }
- }
- if (\is_null($newMixer)) {
- if (\is_null($fallback)) {
- throw new \RuntimeException('Could not find mixer');
- } elseif (!($fallback instanceof Mixer)) {
- throw new \RuntimeException('Invalid Mixer');
- }
- return $fallback;
- } elseif (!($newMixer instanceof Mixer)) {
- throw new \RuntimeException('Invalid Mixer');
- }
- return $newMixer;
- }
- /**
- * Load all core mixing strategies
- *
- * @return void
- * @psalm-suppress InvalidArgument
- */
- protected function loadMixers()
- {
- $this->loadFiles(
- __DIR__ . '/Mixer',
- __NAMESPACE__ . '\\Mixer\\',
- array($this, 'registerMixer')
- );
- }
- /**
- * Load all core random number sources
- *
- * @return void
- * @psalm-suppress InvalidArgument
- */
- protected function loadSources()
- {
- $this->loadFiles(
- __DIR__ . '/Source',
- __NAMESPACE__ . '\\Source\\',
- array($this, 'registerSource')
- );
- }
- }
|