* @copyright 2011 The Authors * @license http://www.opensource.org/licenses/mit-license.html MIT License * @version Build @@version@@ */ namespace CryptLib\Random; use CryptLib\Core\Strength; /** * The Random Factory * * Use this factory to instantiate random number generators, sources and mixers. * * @category PHPCryptLib * @package Random * @author Anthony Ferrara */ class Factory extends \CryptLib\Core\AbstractFactory { /** * @var array A list of available random number mixing strategies */ protected $mixers = array(); /** * @var array 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 * * @return Generator The instantiated generator * @throws RuntimeException If an appropriate mixing strategy isn't found */ public function getGenerator(\CryptLib\Core\Strength $strength) { $sources = $this->getSources(); $newSources = array(); foreach ($sources as $source) { if ($strength->compare($source::getStrength()) <= 0) { $newSources[] = new $source; } } $mixer = $this->findMixer($strength); return new Generator($newSources, $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 An array of mixers */ public function getMixers() { return $this->mixers; } /** * Get all loaded random number sources * * @return array 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 mixer based upon the requested strength * * @param Strength $strength The strength mixer to find * * @return Mixer The found mixer * @throws RuntimeException if a valid mixer cannot be found */ protected function findMixer(\CryptLib\Core\Strength $strength) { $newMixer = null; $fallback = null; foreach ($this->getMixers() as $mixer) { if ($strength->compare($mixer::getStrength()) == 0) { $newMixer = new $mixer; } elseif ($strength->compare($mixer::getStrength()) == 1) { $fallback = new $mixer; } } if (is_null($newMixer)) { if (is_null($fallback)) { throw new \RuntimeException('Could not find mixer'); } return $fallback; } return $newMixer; } /** * Load all core mixing strategies * * @return void */ protected function loadMixers() { $this->loadFiles( __DIR__ . '/Mixer', __NAMESPACE__ . '\\Mixer\\', array($this, 'registerMixer') ); } /** * Load all core random number sources * * @return void */ protected function loadSources() { $this->loadFiles( __DIR__ . '/Source', __NAMESPACE__ . '\\Source\\', array($this, 'registerSource') ); } }