This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
vendor
composer.lock

58
vendor/paragonie/random-lib/.php_cs vendored Normal file
View File

@@ -0,0 +1,58 @@
<?php
$header = <<<'EOF'
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@@
EOF;
Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($header);
return Symfony\CS\Config\Config::create()
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
->fixers([
'align_double_arrow',
'array_element_no_space_before_comma',
'array_element_white_space_after_comma',
'declare_equal_normalize',
'extra_empty_lines',
'header_comment',
'list_commas',
'multiline_array_trailing_comma',
'new_with_braces',
'no_blank_lines_before_namespace',
'no_empty_comment',
'no_empty_lines_after_phpdocs',
'no_empty_phpdoc',
'no_empty_statement',
'object_operator',
'ordered_use',
'php_unit_dedicate_assert',
'phpdoc_indent',
'phpdoc_order',
'phpdoc_params',
'phpdoc_scalar',
'phpdoc_separation',
'remove_leading_slash_use',
'remove_lines_between_uses',
'return',
'self_accessor',
'short_bool_cast',
'short_scalar_cast',
'single_blank_line_before_namespace',
'spaces_before_semicolon',
'ternary_spaces',
'trim_array_spaces',
'unneeded_control_parentheses',
'unused_use',
'whitespacey_lines',
])
->finder(
Symfony\CS\Finder\DefaultFinder::create()
->in(__DIR__ . "/lib")
->in(__DIR__ . "/test")
)
;

View File

@@ -0,0 +1,80 @@
filter:
paths:
- lib/*
checks:
php:
code_rating: true
duplication: true
variable_existence: true
useless_calls: true
use_statement_alias_conflict: true
unused_variables: true
unused_properties: true
unused_parameters: true
unused_methods: true
unreachable_code: true
sql_injection_vulnerabilities: true
security_vulnerabilities: true
precedence_mistakes: true
precedence_in_conditions: true
parameter_non_unique: true
no_property_on_interface: true
no_non_implemented_abstract_methods: true
deprecated_code_usage: true
closure_use_not_conflicting: true
closure_use_modifiable: true
avoid_useless_overridden_methods: true
avoid_conflicting_incrementers: true
assignment_of_null_return: true
verify_access_scope_valid: true
verify_argument_usable_as_reference: true
verify_property_names: true
use_self_instead_of_fqcn: true
uppercase_constants: true
too_many_arguments: true
spacing_of_function_arguments: true
spacing_around_non_conditional_operators: true
spacing_around_conditional_operators: true
space_after_cast: true
single_namespace_per_use: true
scope_indentation:
spaces_per_level: '4'
return_doc_comments: true
return_doc_comment_if_not_inferrable: true
require_scope_for_properties: true
require_scope_for_methods: true
require_php_tag_first: true
property_assignments: true
properties_in_camelcaps: true
php5_style_constructor: true
parameters_in_camelcaps: true
parameter_doc_comments: true
param_doc_comment_if_not_inferrable: true
optional_parameters_at_the_end: true
one_class_per_file: true
no_unnecessary_function_call_in_for_loop: true
no_unnecessary_final_modifier: true
no_trailing_whitespace: true
no_space_inside_cast_operator: true
no_space_before_semicolon: true
no_short_open_tag: true
no_commented_out_code: true
newline_at_end_of_file: true
missing_arguments: true
lowercase_php_keywords: true
lowercase_basic_constants: true
function_in_camel_caps: true
function_body_start_on_same_line: true
ensure_lower_case_builtin_functions: true
classes_in_camel_caps: true
blank_line_after_namespace_declaration: true
avoid_usage_of_logical_operators: true
avoid_todo_comments: true
avoid_tab_indentation: true
avoid_superglobals: true
avoid_fixme_comments: true
avoid_corrupting_byteorder_marks: true
avoid_duplicate_types: true
avoid_closing_tag: true
avoid_aliased_php_functions: true
argument_type_checks: true

41
vendor/paragonie/random-lib/.travis.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
language: php
sudo: required
matrix:
fast_finish: true
include:
- php: "5.3"
env: USE_PSALM=0
dist: precise
- php: "5.4"
env: USE_PSALM=0
- php: "5.5"
env: USE_PSALM=0
- php: "5.6"
env: USE_PSALM=1
- php: "7.0"
env: USE_PSALM=1
- php: "7.1"
env: USE_PSALM=1
- php: "7.2"
env: USE_PSALM=1
- php: "nightly"
env: USE_PSALM=1
- php: "master"
env: USE_PSALM=1
- php: "hhvm"
env: USE_PSALM=1
allow_failures:
- php: "master"
- php: "nightly"
before_script:
- travis_retry composer self-update
- if [[ $USE_PSALM -eq 1 ]]; then composer require --dev "vimeo/psalm:dev-master"; fi
- travis_retry composer install --prefer-source
script:
- make lint
- make test
- if [[ $USE_PSALM -eq 1 ]]; then make typecheck; fi

19
vendor/paragonie/random-lib/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2011 The Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

30
vendor/paragonie/random-lib/Makefile vendored Normal file
View File

@@ -0,0 +1,30 @@
.PHONY: all
all: build
.PHONY: build
build: lint cs test
lintfiles := $(shell find lib test -type f -iname '*.php')
.PHONY: ${lintfiles}
${lintfiles}:
php -l $@
.PHONY: lint
lint: $(lintfiles)
.PHONY: cs
cs:
vendor/bin/php-cs-fixer --quiet --no-interaction fix; true
.PHONY: test
test:
vendor/bin/phpunit
.PHONY: typecheck
typecheck:
vendor/bin/psalm

146
vendor/paragonie/random-lib/README.md vendored Normal file
View File

@@ -0,0 +1,146 @@
RandomLib
=========
[![Build Status](https://travis-ci.org/paragonie/RandomLib.svg?branch=master)](https://travis-ci.org/paragonie/RandomLib)
[![Latest Stable Version](https://poser.pugx.org/paragonie/RandomLib/v/stable)](https://packagist.org/packages/paragonie/RandomLib)
[![Latest Unstable Version](https://poser.pugx.org/paragonie/RandomLib/v/unstable)](https://packagist.org/packages/paragonie/RandomLib)
[![License](https://poser.pugx.org/paragonie/RandomLib/license)](https://packagist.org/packages/paragonie/RandomLib)
A library for generating random numbers and strings of various strengths.
This library is useful in security contexts.
> Note: This is a fork of [Anthony Ferrara's `RandomLib`](https://github.com/ircmaxell/RandomLib),
> maintained by [Paragon Initiative Enterprises](https://paragonie.com).
Install
-------
Via Composer
```sh
$ composer require paragonie/random-lib
```
Usage
-----
### Factory
A factory is used to get generators of varying strength:
```php
$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
```
A factory can be configured with additional mixers and sources but can be
used out of the box to create both medium and low strength generators.
Convenience methods are provided for creating high, medium, and low
strength generators. Example:
```php
$generator = $factory->getMediumStrengthGenerator();
```
#### $factory->getLowStrengthGenerator()
Convenience method to 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.
#### $factory->getMediumStrengthGenerator()
Convenience method to 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
#### $factory->getHighStrengthGenerator()
Convenience method to 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.
### Generator
A generator is used to generate random numbers and strings.
Example:
```php
// Generate a random string that is 32 bytes in length.
$bytes = $generator->generate(32);
// Generate a whole number between 5 and 15.
$randomInt = $generator->generateInt(5, 15);
// Generate a 32 character string that only contains the letters
// 'a', 'b', 'c', 'd', 'e', and 'f'.
$randomString = $generator->generateString(32, 'abcdef');
```
#### $generator->generate($size)
Generate a random byte string of the requested size.
#### $generator->generateInt($min = 0, $max = PHP_INT_MAX)
Generate a random integer with the given range. If range (`$max - $min`)
is zero, `$max` will be used.
#### $generator->generateString($length, $characters = '')
Generate a random string of specified length.
This uses the supplied character list for generating the new result
string. The list of characters should be specified as a string containing
each allowed character.
If no character list is specified, the following list of characters is used:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/
**Examples:**
```php
// Give the character list 'abcdef':
print $generator->generateString(32, 'abcdef')."\n";
// One would expect to receive output that only contained those
// characters:
//
// adaeabecfbddcdaeedaedfbbcdccccfe
// adfbfdbfddadbfcbbefebcacbefafffa
// ceeadbcabecbccacdcaabbdccfadbafe
// abadcffabdcacdbcbafcaecabafcdbbf
// dbdbddacdeaceabfaefcbfafebcacdca
```
License
-------
MIT, see LICENSE.
Community
---------
If you have questions or want to help out, join us in the **#phpc**
channel on **irc.freenode.net**.
Security Vulnerabilities
========================
If you have found a security issue, please contact the author directly at
[security@paragonie.com](mailto:security@paragonie.com).

View File

@@ -0,0 +1,41 @@
{
"name": "paragonie/random-lib",
"type": "library",
"description": "A Library For Generating Secure Random Numbers",
"keywords": ["random", "random-numbers", "random-strings", "cryptography"],
"homepage": "https://github.com/ircmaxell/RandomLib",
"license": "MIT",
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
},
{
"name": "Anthony Ferrara",
"email": "ircmaxell@ircmaxell.com",
"homepage": "http://blog.ircmaxell.com"
}
],
"require-dev": {
"mikey179/vfsStream": "^1.6",
"friendsofphp/php-cs-fixer": "^1.11",
"phpunit/phpunit": "^4.8 || >=5.0.0 <5.4"
},
"require": {
"ircmaxell/security-lib": "^1.1",
"paragonie/random_compat": "^2",
"paragonie/sodium_compat": "^1.3",
"php": ">=5.3.2"
},
"autoload": {
"psr-0": {
"RandomLib": "lib"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
}
}

View File

@@ -0,0 +1,198 @@
<?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 Mcrypt abstract mixer class
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @copyright 2013 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib;
/**
* The mcrypt abstract mixer class
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Chris Smith <chris@cs278.org>
* @author Paragon Initiative Enterprises <security@paragonie.com>
*/
abstract class AbstractMcryptMixer extends AbstractMixer
{
/**
* mcrypt module resource
*
* @var resource
*/
private $mcrypt;
/**
* Block size of cipher
*
* @var int
*/
private $blockSize;
/**
* Cipher initialization vector
*
* @var string
*/
private $initv;
/**
* {@inheritdoc}
*/
public static function test()
{
return extension_loaded('mcrypt');
}
/**
* @return bool
*/
public static function advisable()
{
return static::test() && PHP_VERSION_ID < 70100;
}
/**
* Construct mcrypt mixer
* @psalm-suppress UndefinedConstant
*/
public function __construct()
{
$this->mcrypt = mcrypt_module_open($this->getCipher(), '', MCRYPT_MODE_ECB, '');
$this->blockSize = mcrypt_enc_get_block_size($this->mcrypt);
$this->initv = str_repeat(chr(0), mcrypt_enc_get_iv_size($this->mcrypt));
}
/**
* Performs cleanup
*/
public function __destruct()
{
if ($this->mcrypt) {
mcrypt_module_close($this->mcrypt);
}
}
/**
* Fetch the cipher for mcrypt.
*
* @return string
*/
abstract protected function getCipher();
/**
* {@inheritdoc}
*/
protected function getPartSize()
{
return $this->blockSize;
}
/**
* {@inheritdoc}
*/
protected function mixParts1($part1, $part2)
{
if (!\is_string($part1)) {
throw new \InvalidArgumentException('Expected a string');
}
if (!\is_string($part2)) {
throw new \InvalidArgumentException('Expected a string');
}
return $this->encryptBlock($part1, $part2);
}
/**
* {@inheritdoc}
*/
protected function mixParts2($part1, $part2)
{
if (!\is_string($part1)) {
throw new \InvalidArgumentException('Expected a string');
}
if (!\is_string($part2)) {
throw new \InvalidArgumentException('Expected a string');
}
return $this->decryptBlock($part2, $part1);
}
/**
* Encrypts a block using the suppied key
*
* @param string $input Plaintext to encrypt
* @param string $key Encryption key
*
* @return string Resulting ciphertext
*/
private function encryptBlock($input, $key)
{
if (!$input && !$key) {
return '';
}
$this->prepareCipher($key);
$result = mcrypt_generic($this->mcrypt, $input);
mcrypt_generic_deinit($this->mcrypt);
return $result;
}
/**
* Derypts a block using the suppied key
*
* @param string $input Ciphertext to decrypt
* @param string $key Encryption key
*
* @return string Resulting plaintext
*/
private function decryptBlock($input, $key)
{
if (!$input && !$key) {
return '';
}
$this->prepareCipher($key);
$result = mdecrypt_generic($this->mcrypt, $input);
mcrypt_generic_deinit($this->mcrypt);
return $result;
}
/**
* Sets up the mcrypt module
*
* @param string $key
*
* @return void
*/
private function prepareCipher($key)
{
if (0 !== mcrypt_generic_init($this->mcrypt, $key, $this->initv)) {
throw new \RuntimeException('Failed to prepare mcrypt module');
}
}
}

View File

@@ -0,0 +1,191 @@
<?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@@
*/
/**
* An abstract mixer to implement a common mixing strategy
*
* PHP version 5.3
*
* @category PHPSecurityLib
* @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\Util;
/**
* An abstract mixer to implement a common mixing strategy
*
* @see http://tools.ietf.org/html/rfc4086#section-5.2
*
* @category PHPSecurityLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
*/
abstract class AbstractMixer implements \RandomLib\Mixer
{
/**
* Get the block size (the size of the individual blocks used for the mixing)
*
* @return int The block size
*/
abstract protected function getPartSize();
/**
* Mix 2 parts together using one method
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
abstract protected function mixParts1($part1, $part2);
/**
* Mix 2 parts together using another different method
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
abstract protected function mixParts2($part1, $part2);
/**
* @return bool
*/
public static function advisable()
{
return static::test();
}
/**
* Mix the provided array of strings into a single output of the same size
*
* All elements of the array should be the same size.
*
* @param array<int, string> $parts The parts to be mixed
*
* @return string The mixed result
* @psalm-suppress MixedArgument
*/
public function mix(array $parts)
{
if (empty($parts)) {
return '';
}
/** @var int $len */
$len = Util::safeStrlen($parts[0]);
/** @var array<int, array<int, string>> $parts */
$parts = $this->normalizeParts($parts);
$stringSize = \count($parts[0]);
$partsSize = \count($parts);
/** @var string $result */
$result = '';
/** @var int $offset */
$offset = 0;
for ($i = 0; $i < $stringSize; ++$i) {
/** @var string $stub */
$stub = (string) $parts[$offset][$i];
for ($j = 1; $j < $partsSize; ++$j) {
/** @var string $newKey */
$newKey = $parts[($j + $offset) % $partsSize][$i];
//Alternately mix the output for each source
if ($j % 2 == 1) {
$stub ^= $this->mixParts1($stub, $newKey);
} else {
$stub ^= $this->mixParts2($stub, $newKey);
}
}
$result .= $stub;
$offset = ($offset + 1) % $partsSize;
}
/** @var string $final */
$final = Util::safeSubstr($result, 0, $len);
return $final;
}
/**
* Normalize the part array and split it block part size.
*
* This will make all parts the same length and a multiple
* of the part size
*
* @param array<int, string> $parts The parts to normalize
*
* @return array The normalized and split parts
* @psalm-suppress MissingClosureReturnType
* @psalm-suppress UntypedParam
* @psalm-suppress MissingArgument
*/
protected function normalizeParts(array $parts)
{
if (empty($parts)) {
return $parts;
}
$blockSize = $this->getPartSize();
$callback =
/**
* @var callable $callback
* @param string $value
* @return int
*/
function ($value) {
return (int) Util::safeStrlen($value);
};
$mapped = array_map($callback, $parts);
if (count($mapped) < 1) {
return array();
}
/** @var int $maxSize */
$maxSize = count($mapped) > 1
? max($mapped)
: array_shift($mapped);
if ($maxSize % $blockSize != 0) {
$maxSize += $blockSize - ($maxSize % $blockSize);
}
foreach ($parts as &$part) {
$part = $this->str_pad($part, $maxSize, chr(0));
$part = str_split($part, $blockSize);
}
return $parts;
}
/**
* @param string $string
* @param int $size
* @param string $character
* @return string
*/
private function str_pad($string, $size, $character)
{
$start = Util::safeStrlen($string);
$inc = Util::safeStrlen($character);
for ($i = $start; $i < $size; $i+= $inc) {
$string = $string . $character;
}
return Util::safeSubstr($string, 0, $size);
}
}

View File

@@ -0,0 +1,70 @@
<?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@@
*/
/**
* PHP version 5.3
*
* @category PHPSecurityLib
* @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;
/**
* An abstract mixer to implement a common mixing strategy
*
* @category PHPSecurityLib
* @package Random
*/
abstract class AbstractSource implements \RandomLib\Source
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::VERYLOW);
}
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return true;
}
/**
* Returns a string of zeroes, useful when no entropy is available.
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
protected static function emptyValue($size)
{
return (string) \str_repeat(\chr(0), $size);
}
}

View File

@@ -0,0 +1,290 @@
<?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')
);
}
}

View File

@@ -0,0 +1,386 @@
<?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 Number Generator Class
*
* Use this factory to generate cryptographic quality random numbers (strings)
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @author Timo Hamina
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib;
use SecurityLib\Util;
/**
* The Random Number Generator Class
*
* Use this factory to generate cryptographic quality random numbers (strings)
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @author Timo Hamina
*/
class Generator
{
/**
* @const Flag for uppercase letters
*/
const CHAR_UPPER = 1;
/**
* @const Flag for lowercase letters
*/
const CHAR_LOWER = 2;
/**
* @const Flag for alpha characters (combines UPPER + LOWER)
*/
const CHAR_ALPHA = 3; // CHAR_UPPER | CHAR_LOWER
/**
* @const Flag for digits
*/
const CHAR_DIGITS = 4;
/**
* @const Flag for alpha numeric characters
*/
const CHAR_ALNUM = 7; // CHAR_ALPHA | CHAR_DIGITS
/**
* @const Flag for uppercase hexadecimal symbols
*/
const CHAR_UPPER_HEX = 12; // 8 | CHAR_DIGITS
/**
* @const Flag for lowercase hexidecimal symbols
*/
const CHAR_LOWER_HEX = 20; // 16 | CHAR_DIGITS
/**
* @const Flag for base64 symbols
*/
const CHAR_BASE64 = 39; // 32 | CHAR_ALNUM
/**
* @const Flag for additional symbols accessible via the keyboard
*/
const CHAR_SYMBOLS = 64;
/**
* @const Flag for brackets
*/
const CHAR_BRACKETS = 128;
/**
* @const Flag for punctuation marks
*/
const CHAR_PUNCT = 256;
/**
* @const Flag for upper/lower-case and digits but without "B8G6I1l|0OQDS5Z2"
*/
const EASY_TO_READ = 512;
/**
* @var Mixer The mixing strategy to use for this generator instance
*/
protected $mixer = null;
/**
* @var array<int, Source> An array of random number sources to use for this generator
*/
protected $sources = array();
/**
* @var array<int, string> The different characters, by Flag
*/
protected $charArrays = array(
self::CHAR_UPPER => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
self::CHAR_LOWER => 'abcdefghijklmnopqrstuvwxyz',
self::CHAR_DIGITS => '0123456789',
self::CHAR_UPPER_HEX => 'ABCDEF',
self::CHAR_LOWER_HEX => 'abcdef',
self::CHAR_BASE64 => '+/',
self::CHAR_SYMBOLS => '!"#$%&\'()* +,-./:;<=>?@[\]^_`{|}~',
self::CHAR_BRACKETS => '()[]{}<>',
self::CHAR_PUNCT => ',.;:',
);
/**
* @internal
* @private
* @const string Ambiguous characters for "Easy To Read" sets
*/
const AMBIGUOUS_CHARS = 'B8G6I1l|0OQDS5Z2()[]{}:;,.';
/**
* Build a new instance of the generator
*
* @param array<int, Source> $sources An array of random data sources to use
* @param Mixer $mixer The mixing strategy to use for this generator
*/
public function __construct(array $sources, Mixer $mixer)
{
foreach ($sources as $source) {
$this->addSource($source);
}
$this->mixer = $mixer;
}
/**
* Add a random number source to the generator
*
* @param Source $source The random number source to add
*
* @return Generator $this The current generator instance
*/
public function addSource(Source $source)
{
$this->sources[] = $source;
return $this;
}
/**
* Generate a random number (string) of the requested size
*
* @param int $size The size of the requested random number
*
* @return string The generated random number (string)
*/
public function generate($size)
{
$seeds = array();
foreach ($this->sources as $source) {
if ($source instanceof Source) {
$seeds[] = $source->generate($size);
}
}
return $this->mixer->mix($seeds);
}
/**
* Generate a random integer with the given range
*
* @param int $min The lower bound of the range to generate
* @param int $max The upper bound of the range to generate
*
* @return int The generated random number within the range
*/
public function generateInt($min = 0, $max = PHP_INT_MAX)
{
$tmp = (int) max($max, $min);
$min = (int) min($max, $min);
$max = $tmp;
$range = $max - $min;
if ($range == 0) {
return $max;
} elseif ($range > PHP_INT_MAX || is_float($range) || $range < 0) {
/**
* This works, because PHP will auto-convert it to a float at this point,
* But on 64 bit systems, the float won't have enough precision to
* actually store the difference, so we need to check if it's a float
* and hence auto-converted...
*/
throw new \RangeException(
'The supplied range is too great to generate'
);
}
$bits = $this->countBits($range) + 1;
$bytes = (int) \max(\ceil($bits / 8), 1);
if ($bits == 63) {
/**
* Fixes issue #22
*
* @see https://github.com/ircmaxell/RandomLib/issues/22
*/
$mask = 0x7fffffffffffffff;
} else {
$mask = (int) ((1 << $bits) - 1);
}
/**
* The mask is a better way of dropping unused bits. Basically what it does
* is to set all the bits in the mask to 1 that we may need. Since the max
* range is PHP_INT_MAX, we will never need negative numbers (which would
* have the MSB set on the max int possible to generate). Therefore we
* can just mask that away. Since pow returns a float, we need to cast
* it back to an int so the mask will work.
*
* On a 64 bit platform, that means that PHP_INT_MAX is 2^63 - 1. Which
* is also the mask if 63 bits are needed (by the log(range, 2) call).
* So if the computed result is negative (meaning the 64th bit is set), the
* mask will correct that.
*
* This turns out to be slightly better than the shift as we don't need to
* worry about "fixing" negative values.
*/
do {
$test = $this->generate($bytes);
/** @var int $result */
$result = \hexdec(\bin2hex($test)) & $mask;
} while ($result > $range);
return $result + $min;
}
/**
* Generate a random string of specified length.
*
* This uses the supplied character list for generating the new result
* string.
*
* @param int $length The length of the generated string
* @param int|string $characters String: An optional list of characters to use
* Integer: Character flags
*
* @return string The generated random string
*/
public function generateString($length, $characters = '')
{
if (is_int($characters)) {
// Combine character sets
$characters = $this->expandCharacterSets($characters);
}
if ($length == 0 || strlen($characters) == 1) {
return '';
} elseif (empty($characters)) {
// Default to base 64
$characters = $this->expandCharacterSets(self::CHAR_BASE64);
}
/**
* @var string $characters
*/
// determine how many bytes to generate
// This is basically doing floor(log(strlen($characters)))
// But it's fixed to work properly for all numbers
$len = strlen($characters);
// The max call here fixes an issue where we under-generate in cases
// where less than 8 bits are needed to represent $len
/** @var int $bytes */
$bytes = (int) ($length * ceil(($this->countBits($len)) / 8));
// determine mask for valid characters
$mask = 256 - (256 % $len);
$result = '';
do {
$rand = $this->generate($bytes);
for ($i = 0; $i < $bytes; $i++) {
if (\ord($rand[$i]) >= $mask) {
continue;
}
/** @var int $idx */
$idx = (int) ((int) \ord($rand[$i]) % (int) ($len));
$result .= (string) ($characters[$idx]);
}
} while (Util::safeStrlen($result) < $length);
// We may over-generate, since we always use the entire buffer
return Util::safeSubstr($result, 0, $length);
}
/**
* Get the Mixer used for this instance
*
* @return Mixer the current mixer
*/
public function getMixer()
{
return $this->mixer;
}
/**
* Get the Sources used for this instance
*
* @return array<int, Source> the current mixer
*/
public function getSources()
{
return $this->sources;
}
/**
* Count the minimum number of bits to represent the provided number
*
* This is basically floor(log($number, 2))
* But avoids float precision issues
*
* @param int $number The number to count
*
* @return int The number of bits
*/
protected function countBits($number)
{
$log2 = 0;
while ($number >>= 1) {
$log2++;
}
return $log2;
}
/**
* Expand a character set bitwise spec into a string character set
*
* This will also replace EASY_TO_READ characters if the flag is set
*
* @param int $spec The spec to expand (bitwise combination of flags)
*
* @return string The expanded string
*/
protected function expandCharacterSets($spec)
{
/** @var string $combined */
$combined = '';
if ($spec == self::EASY_TO_READ) {
$spec |= self::CHAR_ALNUM;
}
foreach ($this->charArrays as $flag => $chars) {
if ($flag == self::EASY_TO_READ) {
// handle this later
continue;
}
if (($spec & $flag) === $flag) {
$combined .= $chars;
}
}
if ($spec & self::EASY_TO_READ) {
// remove ambiguous characters
$combined = \str_replace(
\str_split(self::AMBIGUOUS_CHARS),
'',
$combined
);
}
return (string) \count_chars($combined, 3);
}
}

View File

@@ -0,0 +1,77 @@
<?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 Mixer strategy interface.
*
* All mixing strategies must implement this interface
*
* 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;
/**
* The Mixer strategy interface.
*
* All mixing strategies must implement this interface
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @codeCoverageIgnore
*/
interface Mixer
{
/**
* Return an instance of Strength indicating the strength of the mixer
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength();
/**
* Test to see if the mixer is available
*
* @return bool If the mixer is available on the system
*/
public static function test();
/**
* Even if the mixer is available,
*
* @return bool
*/
public static function advisable();
/**
* Mix the provided array of strings into a single output of the same size
*
* All elements of the array should be the same size.
*
* @param array $parts The parts to be mixed
*
* @return string The mixed result
*/
public function mix(array $parts);
}

View File

@@ -0,0 +1,126 @@
<?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 Hash medium strength mixer class
*
* This class implements a mixer based upon the recommendations in RFC 4086
* section 5.2
*
* PHP version 5.3
*
* @see http://tools.ietf.org/html/rfc4086#section-5.2
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib\Mixer;
use SecurityLib\Strength;
use SecurityLib\Util;
/**
* The Hash medium strength mixer class
*
* This class implements a mixer based upon the recommendations in RFC 4086
* section 5.2
*
* @see http://tools.ietf.org/html/rfc4086#section-5.2
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
*/
class Hash extends \RandomLib\AbstractMixer
{
/**
* @var string The hash instance to use
*/
protected $hash = null;
/**
* Build the hash mixer
*
* @param string $hash The hash instance to use (defaults to sha512)
*
* @return void
*/
public function __construct($hash = 'sha512')
{
$this->hash = $hash;
}
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::MEDIUM);
}
/**
* Test to see if the mixer is available
*
* @return bool If the mixer is available on the system
*/
public static function test()
{
return true;
}
/**
* Get the block size (the size of the individual blocks used for the mixing)
*
* @return int The block size
*/
protected function getPartSize()
{
return Util::safeStrlen(hash($this->hash, '', true));
}
/**
* Mix 2 parts together using one method
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
protected function mixParts1($part1, $part2)
{
return hash_hmac($this->hash, $part1, $part2, true);
}
/**
* Mix 2 parts together using another different method
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
protected function mixParts2($part1, $part2)
{
return hash_hmac($this->hash, $part2, $part1, true);
}
}

View File

@@ -0,0 +1,59 @@
<?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@@
*/
/**
* mcrypt mixer using the Rijndael cipher with 128 bit block size
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2013 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib\Mixer;
use RandomLib\AbstractMcryptMixer;
use SecurityLib\Strength;
/**
* mcrypt mixer using the Rijndael cipher with 128 bit block size
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Chris Smith <chris@cs278.org>
*/
class McryptRijndael128 extends AbstractMcryptMixer
{
/**
* {@inheritdoc}
*/
public static function getStrength()
{
return new Strength(Strength::HIGH);
}
/**
* {@inheritdoc}
*/
protected function getCipher()
{
return 'rijndael-128';
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace RandomLib\Mixer;
use RandomLib\AbstractMixer;
use SecurityLib\Strength;
use SecurityLib\Util;
/**
* Class SodiumMixer
*
* @package RandomLib\Mixer
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @copyright 2017 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
class SodiumMixer extends AbstractMixer
{
const SALSA20_BLOCK_SIZE = 64;
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::HIGH);
}
/**
* Test to see if the mixer is available
*
* @return bool If the mixer is available on the system
*/
public static function test()
{
return is_callable('sodium_crypto_stream') && is_callable('sodium_crypto_generichash');
}
/**
* @return bool
*/
public static function advisable()
{
return static::test() && !defined('HHVM_VERSION');
}
/**
* Get the block size (the size of the individual blocks used for the mixing)
*
* @return int The block size
*/
protected function getPartSize()
{
return self::SALSA20_BLOCK_SIZE;
}
/**
* Mix 2 parts together using one method
*
* This method is jut a simple BLAKE2b hash of the two strings
* concatenated together
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
protected function mixParts1($part1, $part2)
{
return (string) \sodium_crypto_generichash($part1 . $part2, '', $this->getPartSize());
}
/**
* Mix 2 parts together using another different method
*
* This method is a salsa20 stream based on a hash of the two inputs
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
protected function mixParts2($part1, $part2)
{
// Pre-hash the two inputs into a 448-bit output
/** @var string $hash */
$hash = \sodium_crypto_generichash($part1 . $part2, '', 56);
// Use salsa20 to expand into a pseudorandom string
return (string) \sodium_crypto_stream(
$this->getPartSize(),
Util::safeSubstr($hash, 0, 24),
Util::safeSubstr($hash, 0, 32)
);
}
}

View File

@@ -0,0 +1,111 @@
<?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 Hash medium strength mixer class
*
* This class implements a mixer based upon the recommendations in RFC 4086
* section 5.2
*
* PHP version 5.3
*
* @see http://tools.ietf.org/html/rfc4086#section-5.2
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @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\Mixer;
use SecurityLib\Strength;
/**
* The Hash medium strength mixer class
*
* This class implements a mixer based upon the recommendations in RFC 4086
* section 5.2
*
* @see http://tools.ietf.org/html/rfc4086#section-5.2
*
* @category PHPCryptLib
* @package Random
* @subpackage Mixer
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
*/
class XorMixer extends \RandomLib\AbstractMixer
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::VERYLOW);
}
/**
* Test to see if the mixer is available
*
* @return bool If the mixer is available on the system
*/
public static function test()
{
return true;
}
/**
* Get the block size (the size of the individual blocks used for the mixing)
*
* @return int The block size
*/
protected function getPartSize()
{
return 64;
}
/**
* Mix 2 parts together using one method
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
protected function mixParts1($part1, $part2)
{
return (string) ($part1 ^ $part2);
}
/**
* Mix 2 parts together using another different method
*
* @param string $part1 The first part to mix
* @param string $part2 The second part to mix
*
* @return string The mixed data
*/
protected function mixParts2($part1, $part2)
{
// Both mixers are identical, this is for speed, not security
return (string) ($part1 ^ $part2);
}
}

View File

@@ -0,0 +1,70 @@
<?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 Number Source interface.
*
* All random number sources must implement this interface
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib;
/**
* The Random Number Source interface.
*
* All random number sources must implement this interface
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @codeCoverageIgnore
*/
interface Source
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength();
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported();
/**
* Generate a random string of the specified size
*
* Note: If the source fails to generate enough data, the result must be
* padded to the requested length.
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size);
}

View File

@@ -0,0 +1,104 @@
<?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 Capicom Random Number Source
*
* This uses the Windows CapiCom Com object to generate random numbers
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @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\Source;
use SecurityLib\Strength;
/**
* The Capicom Random Number Source
*
* This uses the Windows CapiCom Com object to generate random numbers
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @codeCoverageIgnore
*/
class CAPICOM extends \RandomLib\AbstractSource
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::MEDIUM);
}
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return class_exists('\\COM', false);
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
if (!\class_exists('COM', false)) {
/** @var string $result */
$result = static::emptyValue($size);
return $result;
}
try {
/** @var \COM $util */
$util = new \COM('CAPICOM.Utilities.1');
if (!\method_exists($util, 'GetRandom')) {
/** @var string $result */
$result = static::emptyValue($size);
return $result;
}
$data = base64_decode((string) $util->GetRandom($size, 0));
return (string) str_pad($data, $size, chr(0));
} catch (\Exception $e) {
unset($e);
/** @var string $result */
$result = static::emptyValue($size);
return $result;
}
}
}

View File

@@ -0,0 +1,85 @@
<?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 MTRand Random Number Source
*
* This source generates low strength random numbers by using the internal
* mt_rand() function. By itself it is quite weak. However when combined with
* other sources it does provide significant benefit.
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @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\Source;
use SecurityLib\Strength;
/**
* The MTRand Random Number Source
*
* This source generates low strength random numbers by using the internal
* mt_rand() function. By itself it is quite weak. However when combined with
* other sources it does provide significant benefit.
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @codeCoverageIgnore
*/
class MTRand extends \RandomLib\AbstractSource
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
// Detect if Suhosin Hardened PHP patch is applied
if (defined('S_ALL')) {
return new Strength(Strength::LOW);
} else {
return new Strength(Strength::VERYLOW);
}
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
$result = '';
for ($i = 0; $i < $size; $i++) {
$result .= chr((mt_rand() ^ mt_rand()) % 256);
}
return $result;
}
}

View File

@@ -0,0 +1,141 @@
<?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 Microtime Random Number Source
*
* This uses the current micro-second (looped several times) for a **very** weak
* random number source. This is only useful when combined with several other
* stronger sources
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @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\Source;
use SecurityLib\Util;
/**
* The Microtime Random Number Source
*
* This uses the current micro-second (looped several times) for a **very** weak
* random number source. This is only useful when combined with several other
* stronger sources
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @codeCoverageIgnore
*/
final class MicroTime extends \RandomLib\AbstractSource
{
/**
* A static counter to ensure unique hashes and prevent state collisions
*
* @var int A counter
*/
private static $counter = null;
/**
* The current state of the random number generator.
*
* @var string The state of the PRNG
*/
private static $state = '';
public function __construct()
{
$state = self::$state;
if (function_exists('posix_times')) {
$state .= serialize(posix_times());
}
if (!defined('HHVM_VERSION') && function_exists('zend_thread_id')) {
$state .= zend_thread_id();
}
if (function_exists('hphp_get_thread_id')) {
$state .= hphp_get_thread_id();
}
$state .= getmypid() . memory_get_usage();
$state .= serialize($_ENV);
$state .= serialize($_SERVER);
$state .= count(debug_backtrace(false));
self::$state = hash('sha512', $state, true);
if (is_null(self::$counter)) {
list(, self::$counter) = unpack("i", Util::safeSubstr(self::$state, 0, 4));
$seed = $this->generate(Util::safeStrlen(dechex(PHP_INT_MAX)));
list(, self::$counter) = unpack("i", $seed);
}
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
$result = '';
/** @var string $seed */
$seed = (string) \microtime() . \memory_get_usage();
self::$state = hash('sha512', self::$state . $seed, true);
/**
* Make the generated randomness a bit better by forcing a GC run which
* should complete in a indeterminate amount of time, hence improving
* the strength of the randomness a bit. It's still not crypto-safe,
* but at least it's more difficult to predict.
*/
gc_collect_cycles();
for ($i = 0; $i < $size; $i += 8) {
$seed = self::$state .
(string) \microtime() .
(string) \pack('Ni', $i, self::counter());
self::$state = \hash('sha512', $seed, true);
/**
* We only use the first 8 bytes here to prevent exposing the state
* in its entirety, which could potentially expose other random
* generations in the future (in the same process)...
*/
$result .= Util::safeSubstr(self::$state, 0, 8);
}
return Util::safeSubstr($result, 0, $size);
}
/**
* @return int
*/
private static function counter()
{
if (self::$counter >= PHP_INT_MAX) {
self::$counter = -1 * PHP_INT_MAX - 1;
} else {
self::$counter++;
}
return self::$counter;
}
}

View File

@@ -0,0 +1,123 @@
<?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 OpenSSL Random Number Source
*
* This uses the OS's secure generator to generate high strength numbers
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @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\Source;
use SecurityLib\Strength;
/**
* The OpenSSL Random Number Source
*
* This uses the OS's secure generator to generate high strength numbers
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @codeCoverageIgnore
*/
class OpenSSL extends \RandomLib\AbstractSource
{
/**
* Return an instance of Strength indicating the strength of the source
*
* PIE notes: Userland PRNGs are not high strength. OpenSSL is, at best, medium.
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
/**
* Prior to PHP 5.6.12 (see https://bugs.php.net/bug.php?id=70014) the "openssl_random_pseudo_bytes"
* was using "RAND_pseudo_bytes" (predictable) instead of "RAND_bytes" (unpredictable).
* Release notes: http://php.net/ChangeLog-5.php#5.6.12
*/
if (PHP_VERSION_ID >= 50612) {
return new Strength(Strength::MEDIUM);
}
/**
* Prior to PHP 5.5.28 (see https://bugs.php.net/bug.php?id=70014) the "openssl_random_pseudo_bytes"
* was using "RAND_pseudo_bytes" (predictable) instead of "RAND_bytes" (unpredictable).
* Release notes: http://php.net/ChangeLog-5.php#5.5.28
*/
if (PHP_VERSION_ID >= 50528 && PHP_VERSION_ID < 50600) {
return new Strength(Strength::MEDIUM);
}
/**
* Prior to PHP 5.4.44 (see https://bugs.php.net/bug.php?id=70014) the "openssl_random_pseudo_bytes"
* was using "RAND_pseudo_bytes" (predictable) instead of "RAND_bytes" (unpredictable).
* Release notes: http://php.net/ChangeLog-5.php#5.4.44
*/
if (PHP_VERSION_ID >= 50444 && PHP_VERSION_ID < 50500) {
return new Strength(Strength::MEDIUM);
}
return new Strength(Strength::LOW);
}
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return \is_callable('openssl_random_pseudo_bytes');
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
if ($size < 1) {
return str_repeat(chr(0), $size);
}
/**
* PIE notes: This $crypto_string argument doesn't do what people think
* it does. Original comment follows.
*
* Note, normally we would check the return of of $crypto_strong to
* ensure that we generated a good random string. However, since we're
* using this as one part of many sources a low strength random number
* shouldn't be much of an issue.
*/
return openssl_random_pseudo_bytes($size);
}
}

View File

@@ -0,0 +1,83 @@
<?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 Rand Random Number Source
*
* This source generates low strength random numbers by using the internal
* rand() function. By itself it is quite weak. However when combined with
* other sources it does provide significant benefit.
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
/**
* The Rand Random Number Source
*
* This source generates low strength random numbers by using the internal
* rand() function. By itself it is quite weak. However when combined with
* other sources it does provide significant benefit.
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @codeCoverageIgnore
*/
class Rand extends \RandomLib\AbstractSource
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
// Detect if Suhosin Hardened PHP patch is applied
if (defined('S_ALL')) {
return new Strength(Strength::LOW);
} else {
return new Strength(Strength::VERYLOW);
}
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
$result = '';
for ($i = 0; $i < $size; $i++) {
$result .= chr((rand() ^ rand()) % 256);
}
return $result;
}
}

View File

@@ -0,0 +1,85 @@
<?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 PHP7 Random Number Source
*
* This uses the inbuilt PHP7 Random Bytes function
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @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\Source;
use SecurityLib\Strength;
/**
* The PHP7 Random Number Source
*
* This uses the php7 secure generator to generate high strength numbers
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
*/
class RandomBytes extends \RandomLib\AbstractSource
{
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return \is_callable('random_bytes');
}
/**
* Return an instance of Strength indicating the strength of the source
*
* @return Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::HIGH);
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
if (!self::isSupported()) {
return \str_repeat(chr(0), $size);
}
return \random_bytes($size);
}
}

View File

@@ -0,0 +1,111 @@
<?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 libsodium Random Number Source
*
* This uses the libsodium secure generator to generate high strength numbers
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Ben Ramsey <ben@benramsey.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@@
*
* @link https://paragonie.com/book/pecl-libsodium
* @link http://pecl.php.net/package/libsodium
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
/**
* The libsodium Random Number Source
*
* This uses the libsodium secure generator to generate high strength numbers
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Ben Ramsey <ben@benramsey.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
*/
class Sodium extends \RandomLib\AbstractSource
{
/**
* A property that may be forcibly set to `false` in the constructor, for
* the purpose of testing this source
*
* @var bool
*/
private $hasLibsodium = false;
/**
* Constructs a libsodium Random Number Source
*
* @param bool $useLibsodium May be set to `false` to disable libsodium for
* testing purposes
*/
public function __construct($useLibsodium = true)
{
if ($useLibsodium && extension_loaded('libsodium')) {
$this->hasLibsodium = true;
}
}
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return function_exists('Sodium\\randombytes_buf');
}
/**
* Return an instance of Strength indicating the strength of the source
*
* @return Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::HIGH);
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
if (!$this->hasLibsodium || $size < 1) {
return str_repeat(chr(0), $size);
}
return (string) \Sodium\randombytes_buf($size);
}
}

View File

@@ -0,0 +1,108 @@
<?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 URandom Random Number Source
*
* This uses the *nix /dev/urandom device to generate medium strength numbers
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @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\Source;
use SecurityLib\Strength;
/**
* The URandom Random Number Source
*
* This uses the *nix /dev/urandom device to generate medium strength numbers
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @author Paragon Initiative Enterprises <security@paragonie.com>
* @codeCoverageIgnore
*/
class URandom extends \RandomLib\AbstractSource
{
/**
* @var string The file to read from
*/
protected static $file = '/dev/urandom';
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::HIGH);
}
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return (bool) @\file_exists(static::$file);
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
if ($size == 0) {
return static::emptyValue($size);
}
$file = \fopen(static::$file, 'rb');
if (!\is_resource($file)) {
/** @var string $result */
$result = static::emptyValue($size);
return $result;
}
if (\is_callable('stream_set_read_buffer')) {
\stream_set_read_buffer($file, 0);
}
/** @var string $result */
$result = \fread($file, $size);
if (!\is_string($result)) {
/** @var string $result */
$result = static::emptyValue($size);
return $result;
}
\fclose($file);
return $result;
}
}

View File

@@ -0,0 +1,77 @@
<?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 UniqID Random Number Source
*
* This uses the internal `uniqid()` function to generate low strength random
* numbers.
*
* PHP version 5.3
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*
* @version Build @@version@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
use SecurityLib\Util;
/**
* The UniqID Random Number Source
*
* This uses the internal `uniqid()` function to generate low strength random
* numbers.
*
* @category PHPCryptLib
* @package Random
* @subpackage Source
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @codeCoverageIgnore
*/
class UniqID extends \RandomLib\AbstractSource
{
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return new Strength(Strength::LOW);
}
/**
* Generate a random string of the specified size
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
$result = '';
while (Util::safeStrlen($result) < $size) {
$result = uniqid($result, true);
}
return Util::safeSubstr($result, 0, $size);
}
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="true"
backupStaticAttributes="false"
bootstrap="test/bootstrap.php"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
forceCoversAnnotation="false"
mapTestClassNameToCoveredClassName="false"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
strict="false"
verbose="false">
<testsuites>
<testsuite name="Unit">
<directory>test/Unit</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">lib/</directory>
</whitelist>
</filter>
</phpunit>

29
vendor/paragonie/random-lib/psalm.xml vendored Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<psalm
name="Example Psalm config with recommended defaults"
stopOnFirstError="false"
useDocblockTypes="true"
totallyTyped="true"
>
<projectFiles>
<directory name="lib" />
</projectFiles>
<!--
<issueHandlers>
<LessSpecificReturnType errorLevel="info" />
<DeprecatedMethod errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />
<MissingPropertyType errorLevel="info" />
<InvalidDocblock errorLevel="info" />
<MisplacedRequiredParam errorLevel="info" />
<PropertyNotSetInConstructor errorLevel="info" />
<MissingConstructor errorLevel="info" />
<UntypedParam errorLevel="info" />
</issueHandlers>
-->
</psalm>

View File

@@ -0,0 +1,56 @@
<?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 interface that all hash implementations must implement
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package Hash
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @license http://www.gnu.org/licenses/lgpl-2.1.html LGPL v 2.1
*/
namespace RandomLibtest\Mocks;
/**
* The interface that all hash implementations must implement
*
* @category PHPPasswordLib
* @package Hash
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
*/
class AbstractMock
{
protected $callbacks = array();
public static function init()
{
}
public function __construct(array $callbacks = array())
{
$this->callbacks = $callbacks;
}
public function __call($name, array $args = array())
{
if (isset($this->callbacks[$name])) {
return call_user_func_array($this->callbacks[$name], $args);
}
return null;
}
}

View File

@@ -0,0 +1,80 @@
<?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 Mixer strategy interface.
*
* All mixing strategies must implement this interface
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @license http://www.gnu.org/licenses/lgpl-2.1.html LGPL v 2.1
*/
namespace RandomLibtest\Mocks\Random;
/**
* The Mixer strategy interface.
*
* All mixing strategies must implement this interface
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
*/
class Generator extends \RandomLib\Generator
{
protected $callbacks = array();
public static function init()
{
}
public function __construct(array $callbacks = array())
{
$this->callbacks = $callbacks;
}
public function __call($name, array $args = array())
{
if (isset($this->callbacks[$name])) {
return call_user_func_array($this->callbacks[$name], $args);
}
return null;
}
public function addSource(\PasswordLib\Random\Source $source)
{
return $this->__call('addSource', array($source));
}
public function generate($size)
{
return $this->__call('generate', array($size));
}
public function generateInt($min = 0, $max = \PHP_INT_MAX)
{
return $this->__call('generateInt', array($min, $max));
}
public function generateString($length, $chars = '')
{
return $this->__call('generateString', array($length, $chars));
}
}

View File

@@ -0,0 +1,86 @@
<?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 Mixer strategy interface.
*
* All mixing strategies must implement this interface
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @license http://www.gnu.org/licenses/lgpl-2.1.html LGPL v 2.1
*/
namespace RandomLibtest\Mocks\Random;
use SecurityLib\Strength;
/**
* The Mixer strategy interface.
*
* All mixing strategies must implement this interface
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
*/
class Mixer extends \RandomLibTest\Mocks\AbstractMock implements \RandomLib\Mixer
{
public static $strength = null;
public static $test = true;
public static function init()
{
static::$strength = new Strength(Strength::HIGH);
static::$test = true;
}
/**
* Return an instance of Strength indicating the strength of the mixer
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return static::$strength;
}
/**
* Test to see if the mixer is available
*
* @return bool If the mixer is available on the system
*/
public static function test()
{
return static::$test;
}
/**
* Mix the provided array of strings into a single output of the same size
*
* All elements of the array should be the same size.
*
* @param array $parts The parts to be mixed
*
* @return string The mixed result
*/
public function mix(array $parts)
{
return $this->__call('mix', array($parts));
}
}

View File

@@ -0,0 +1,85 @@
<?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 Number Source interface.
*
* All random number sources must implement this interface
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @license http://www.gnu.org/licenses/lgpl-2.1.html LGPL v 2.1
*/
namespace RandomLibtest\Mocks\Random;
use SecurityLib\Strength;
/**
* The Random Number Source interface.
*
* All random number sources must implement this interface
*
* @category PHPPasswordLib
* @package Random
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
*/
class Source extends \RandomLibTest\Mocks\AbstractMock implements \RandomLib\Source
{
public static $strength = null;
public static function init()
{
static::$strength = new Strength(Strength::VERYLOW);
}
/**
* Return an instance of Strength indicating the strength of the source
*
* @return \SecurityLib\Strength An instance of one of the strength classes
*/
public static function getStrength()
{
return static::$strength;
}
/**
* If the source is currently available.
* Reasons might be because the library is not installed
*
* @return bool
*/
public static function isSupported()
{
return true;
}
/**
* Generate a random string of the specified size
*
* Note: If the source fails to generate enough data, the result must be
* padded to the requested length.
*
* @param int $size The size of the requested random string
*
* @return string A string of the requested size
*/
public function generate($size)
{
return $this->__call('generate', array($size));
}
}

View File

@@ -0,0 +1,68 @@
<?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@@
*/
namespace RandomLib;
use SecurityLib\Strength;
class FactoryTest extends \PHPUnit_Framework_TestCase
{
public function testConstruct()
{
$factory = new Factory();
$this->assertTrue($factory instanceof Factory);
}
public function testGetGeneratorFallback()
{
$factory = new Factory();
$generator = $factory->getGenerator(new Strength(Strength::VERYLOW));
$mixer = call_user_func(array(
get_class($generator->getMixer()),
'getStrength',
));
$this->assertTrue($mixer->compare(new Strength(Strength::VERYLOW)) <= 0);
}
/**
* @covers RandomLib\Factory::getMediumStrengthGenerator
* @covers RandomLib\Factory::getGenerator
* @covers RandomLib\Factory::findMixer
* @covers RandomLib\Factory::findSources
*/
public function testGetMediumStrengthGenerator()
{
$factory = new Factory();
$generator = $factory->getMediumStrengthGenerator();
$this->assertTrue($generator instanceof Generator);
$mixer = call_user_func(array(
get_class($generator->getMixer()),
'getStrength',
));
$this->assertTrue($mixer->compare(new Strength(Strength::MEDIUM)) <= 0);
foreach ($generator->getSources() as $source) {
$strength = call_user_func(array(get_class($source), 'getStrength'));
$this->assertTrue($strength->compare(new Strength(Strength::MEDIUM)) >= 0);
}
}
/**
* @expectedException RuntimeException
* @expectedExceptionMessage Could not find sources
*/
public function testNoAvailableSource()
{
$factory = new Factory();
$sources = new \ReflectionProperty($factory, 'sources');
$sources->setAccessible(true);
$sources->setValue($factory, array());
$factory->getMediumStrengthGenerator();
}
}

View File

@@ -0,0 +1,111 @@
<?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@@
*/
namespace RandomLib;
class GeneratorStringTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Generator
*/
protected $generator = null;
/**
* @var Mixer
*/
protected $mixer = null;
/**
* @var array<int, Source>
*/
protected $sources = array();
public static function provideCharCombinations()
{
return array(
array("CHAR_LOWER", implode("", range("a", "z"))),
array("CHAR_UPPER", implode("", range("A", "Z"))),
array("CHAR_DIGITS", implode("", range(0, 9))),
array("CHAR_UPPER_HEX", "0123456789ABCDEF"),
array("CHAR_LOWER_HEX", "0123456789abcdef"),
array("CHAR_BASE64", "+/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
array("EASY_TO_READ", "3479ACEFHJKLMNPRTUVWXYabcdefghijkmnopqrstuvwxyz"),
array("CHAR_BRACKETS", "()<>[]{}"),
array("CHAR_SYMBOLS", " !\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"),
array("CHAR_PUNCT", ",.:;"),
array("CHAR_ALPHA", implode("", array_merge(range("A", "Z"), range("a", "z")))),
array("CHAR_ALNUM", implode("", array_merge(range(0, 9), range("A", "Z"), range("a", "z")))),
array("CHAR_ALPHA | PUNCT", ",.:;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", Generator::CHAR_ALPHA | Generator::CHAR_PUNCT),
array("CHAR_LOWER | EASY_TO_READ", "abcdefghijkmnopqrstuvwxyz", Generator::CHAR_LOWER | Generator::EASY_TO_READ),
array("CHAR_DIGITS | EASY_TO_READ", "3479", Generator::CHAR_DIGITS | Generator::EASY_TO_READ),
);
}
public function setUp()
{
$source1 = $this->getMock('RandomLib\Source');
$source1->expects($this->any())
->method('generate')
->will($this->returnCallback(function ($size) {
$r = '';
for ($i = 0; $i < $size; $i++) {
$r .= chr($i % 256);
}
return $r;
}
));
$source2 = $this->getMock('RandomLib\Source');
$source2->expects($this->any())
->method('generate')
->will($this->returnCallback(function ($size) {
$r = '';
for ($i = 0; $i < $size; $i++) {
$r .= chr(0);
}
return $r;
}
));
$this->mixer = $this->getMock('RandomLib\Mixer');
$this->mixer->expects($this->any())
->method('mix')
->will($this->returnCallback(function (array $sources) {
if (empty($sources)) {
return '';
}
$start = array_pop($sources);
// throw new \Exception('test');
return array_reduce(
$sources,
function ($el1, $el2) {
return $el1 ^ $el2;
},
$start
);
}));
$this->sources = array($source1, $source2);
$this->generator = new Generator($this->sources, $this->mixer);
}
/**
* @dataProvider provideCharCombinations
*/
public function testScheme($schemeName, $expected, $scheme = 0)
{
// test for overspecification by doubling the expected amount
if (!$scheme) {
$scheme = constant("RandomLib\Generator::$schemeName");
}
$chars = $this->generator->generateString(strlen($expected) * 2, $scheme);
$this->assertEquals($expected . $expected, $chars, sprintf("Testing Generator::%s failed", $schemeName));
}
}

View File

@@ -0,0 +1,202 @@
<?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@@
*/
namespace RandomLib;
class GeneratorTest extends \PHPUnit_Framework_TestCase
{
protected $generator = null;
protected $mixer = null;
protected $sources = array();
public static function provideGenerate()
{
return array(
array(0, ''),
array(1, chr(0)),
array(2, chr(1) . chr(1)),
array(3, chr(2) . chr(0) . chr(2)),
array(4, chr(3) . chr(3) . chr(3) . chr(3)),
);
}
public static function provideGenerateInt()
{
return array(
array(1, 1, 1),
array(0, 1, 0),
array(0, 255, 0),
array(400, 655, 400),
array(0, 65535, 257),
array(65535, 131070, 65792),
array(0, 16777215, (2<<16) + 2),
array(-10, 0, -10),
array(-655, -400, -655),
array(-131070, -65535, -130813),
);
}
public static function provideGenerateIntRangeTest()
{
return array(
array(0, 0),
array(0, 1),
array(1, 10000),
array(100000, \PHP_INT_MAX),
);
}
public static function provideGenerateStringTest()
{
return array(
array(0, 'ab', ''),
array(1, 'ab', 'a'),
array(1, 'a', ''),
array(2, 'ab', 'bb'),
array(3, 'abc', 'cac'),
array(8, '0123456789abcdef', '77777777'),
array(16, '0123456789abcdef', 'ffffffffffffffff'),
array(16, '', 'DDDDDDDDDDDDDDDD'),
);
}
public function setUp()
{
$source1 = $this->getMock('RandomLib\Source');
$source1->expects($this->any())
->method('generate')
->will($this->returnCallback(function ($size) {
$r = '';
for ($i = 0; $i < $size; $i++) {
$r .= chr($i);
}
return $r;
}
));
$source2 = $this->getMock('RandomLib\Source');
$source2->expects($this->any())
->method('generate')
->will($this->returnCallback(function ($size) {
$r = '';
for ($i = $size - 1; $i >= 0; $i--) {
$r .= chr($i);
}
return $r;
}
));
$this->mixer = $this->getMock('RandomLib\Mixer');
$this->mixer->expects($this->any())
->method('mix')
->will($this->returnCallback(function (array $sources) {
if (empty($sources)) {
return '';
}
$start = array_pop($sources);
return array_reduce(
$sources,
function ($el1, $el2) {
return $el1 ^ $el2;
},
$start
);
}));
$this->sources = array($source1, $source2);
$this->generator = new Generator($this->sources, $this->mixer);
}
public function testConstruct()
{
$this->assertTrue($this->generator instanceof Generator);
}
public function testGetMixer()
{
$this->assertSame($this->mixer, $this->generator->getMixer());
}
public function testGetSources()
{
$this->assertSame($this->sources, $this->generator->getSources());
}
/**
* @dataProvider provideGenerate
*/
public function testGenerate($size, $expect)
{
$this->assertEquals($expect, $this->generator->generate($size));
}
/**
* @dataProvider provideGenerateInt
*/
public function testGenerateInt($min, $max, $expect)
{
$this->assertEquals($expect, $this->generator->generateInt($min, $max));
}
/**
* @dataProvider provideGenerateIntRangeTest
*/
public function testGenerateIntRange($min, $max)
{
$n = $this->generator->generateInt($min, $max);
$this->assertTrue($min <= $n);
$this->assertTrue($max >= $n);
}
/**
* @expectedException RangeException
*/
public function testGenerateIntFail()
{
$n = $this->generator->generateInt(-1, PHP_INT_MAX);
}
public function testGenerateIntLargeTest()
{
$bits = 30;
$expected = 50529027;
if (PHP_INT_MAX > 4000000000) {
$bits = 55;
$expected = 1693273676973062;
}
$n = $this->generator->generateInt(0, (int) pow(2, $bits));
$this->assertEquals($expected, $n);
}
/**
* @dataProvider provideGenerateStringTest
*/
public function testGenerateString($length, $chars, $expected)
{
$n = $this->generator->generateString($length, $chars);
$this->assertEquals($expected, $n);
}
/**
* This test checks for issue #22:
*
* @see https://github.com/ircmaxell/RandomLib/issues/22
*/
public function testGenerateLargeRange()
{
if (PHP_INT_MAX < pow(2, 32)) {
$this->markTestSkipped("Only test on 64 bit platforms");
}
$this->assertEquals(506381209866536711, $this->generator->generateInt(0, PHP_INT_MAX));
}
}

View File

@@ -0,0 +1,63 @@
<?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@@
*/
namespace RandomLib\Mixer;
use SecurityLib\Strength;
class HashTest extends \PHPUnit_Framework_TestCase
{
public static function provideMix()
{
$data = array(
array(array(), ''),
array(array('1', '1'), '0d'),
array(array('a'), '61'),
// This expects 'b' because of how the mock hmac function works
array(array('a', 'b'), '9a'),
array(array('aa', 'ba'), '6e84'),
array(array('ab', 'bb'), 'b0cb'),
array(array('aa', 'bb'), 'ae8d'),
array(array('aa', 'bb', 'cc'), 'a14c'),
array(array('aabbcc', 'bbccdd', 'ccddee'), 'a8aff3939934'),
);
return $data;
}
public function testConstructWithoutArgument()
{
$hash = new Hash();
$this->assertTrue($hash instanceof \RandomLib\Mixer);
}
public function testGetStrength()
{
$strength = new Strength(Strength::MEDIUM);
$actual = Hash::getStrength();
$this->assertEquals($actual, $strength);
}
public function testTest()
{
$actual = Hash::test();
$this->assertTrue($actual);
}
/**
* @dataProvider provideMix
*/
public function testMix($parts, $result)
{
$mixer = new Hash('md5');
$actual = $mixer->mix($parts);
$this->assertEquals($result, bin2hex($actual));
}
}

View File

@@ -0,0 +1,69 @@
<?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@@
*/
namespace RandomLib\Mixer;
use SecurityLib\Strength;
class McryptRijndael128Test extends \PHPUnit_Framework_TestCase
{
public static function provideMix()
{
$data = array(
array(array(), ''),
array(array('', ''), ''),
array(array('a'), '61'),
array(array('a', 'b'), '6a'),
array(array('aa', 'ba'), '688d'),
array(array('ab', 'bb'), 'f8bc'),
array(array('aa', 'bb'), 'a0f3'),
array(array('aa', 'bb', 'cc'), '87c3'),
array(array('aabbcc', 'bbccdd', 'ccddee'), '7cf2273e46c7'),
);
return $data;
}
protected function setUp()
{
if (!\extension_loaded('mcrypt') || PHP_VERSION_ID >= 70100) {
$this->markTestSkipped('mcrypt extension is not available');
}
}
public function testConstructWithoutArgument()
{
$hash = new McryptRijndael128();
$this->assertTrue($hash instanceof \RandomLib\Mixer);
}
public function testGetStrength()
{
$strength = new Strength(Strength::HIGH);
$actual = McryptRijndael128::getStrength();
$this->assertEquals($actual, $strength);
}
public function testTest()
{
$actual = McryptRijndael128::test();
$this->assertTrue($actual);
}
/**
* @dataProvider provideMix
*/
public function testMix($parts, $result)
{
$mixer = new McryptRijndael128();
$actual = $mixer->mix($parts);
$this->assertEquals($result, bin2hex($actual));
}
}

View File

@@ -0,0 +1,69 @@
<?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@@
*/
namespace RandomLib\Mixer;
use SecurityLib\Strength;
class SodiumTest extends \PHPUnit_Framework_TestCase
{
public static function provideMix()
{
$data = array(
array(array(), ''),
array(array('', ''), ''),
array(array('a'), '61'),
array(array('a', 'b'), '44'),
array(array('aa', 'ba'), '6967'),
array(array('ab', 'bb'), '73a6'),
array(array('aa', 'bb'), 'bc7b'),
array(array('aa', 'bb', 'cc'), '0cbd'),
array(array('aabbcc', 'bbccdd', 'ccddee'), '5f0005cacd7c'),
);
return $data;
}
protected function setUp()
{
if (!\is_callable('sodium_crypto_generichash') || defined('HHVM_VERSION')) {
$this->markTestSkipped('sodium extension is not available');
}
}
public function testConstructWithoutArgument()
{
$hash = new SodiumMixer();
$this->assertTrue($hash instanceof \RandomLib\Mixer);
}
public function testGetStrength()
{
$strength = new Strength(Strength::HIGH);
$actual = SodiumMixer::getStrength();
$this->assertEquals($actual, $strength);
}
public function testTest()
{
$actual = SodiumMixer::test();
$this->assertTrue($actual);
}
/**
* @dataProvider provideMix
*/
public function testMix($parts, $result)
{
$mixer = new SodiumMixer();
$actual = $mixer->mix($parts);
$this->assertEquals($result, bin2hex($actual));
}
}

View File

@@ -0,0 +1,67 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
abstract class AbstractSourceTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$class = static::getTestedClass();
if (!$class::isSupported()) {
$this->markTestSkipped();
}
}
protected static function getTestedClass()
{
return preg_replace('/Test$/', '', get_called_class());
}
protected static function getExpectedStrength()
{
return new Strength(Strength::VERYLOW);
}
public static function provideGenerate()
{
$data = array();
for ($i = 0; $i < 100; $i += 5) {
$not = $i > 0 ? str_repeat(chr(0), $i) : chr(0);
$data[] = array($i, $not);
}
return $data;
}
public function testGetStrength()
{
$class = static::getTestedClass();
$strength = static::getExpectedStrength();
$actual = $class::getStrength();
$this->assertEquals($actual, $strength);
}
/**
* @dataProvider provideGenerate
* @group slow
*/
public function testGenerate($length, $not)
{
$class = static::getTestedClass();
$rand = new $class();
$stub = $rand->generate($length);
$this->assertEquals($length, strlen($stub));
$this->assertNotEquals($not, $stub);
}
}

View File

@@ -0,0 +1,21 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class CAPICOMTest extends AbstractSourceTest
{
protected static function getExpectedStrength()
{
return new Strength(Strength::MEDIUM);
}
}

View File

@@ -0,0 +1,25 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class MTRandTest extends AbstractSourceTest
{
protected static function getExpectedStrength()
{
if (defined('S_ALL')) {
return new Strength(Strength::LOW);
} else {
return new Strength(Strength::VERYLOW);
}
}
}

View File

@@ -0,0 +1,33 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class MicroTimeTest extends AbstractSourceTest
{
protected static function getExpectedStrength()
{
return new Strength(Strength::VERYLOW);
}
/**
* Test the initialization of the static counter (!== 0)
*/
public function testCounterNotNull()
{
$class = static::getTestedClass();
$rand = new $class();
$reflection_class = new \ReflectionClass($class);
$static = $reflection_class->getStaticProperties();
$this->assertTrue($static['counter'] !== 0);
}
}

View File

@@ -0,0 +1,25 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class RandTest extends AbstractSourceTest
{
protected static function getExpectedStrength()
{
if (defined('S_ALL')) {
return new Strength(Strength::LOW);
} else {
return new Strength(Strength::VERYLOW);
}
}
}

View File

@@ -0,0 +1,88 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class SodiumTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!extension_loaded('libsodium')) {
$this->markTestSkipped('The libsodium extension is not loaded');
}
}
public static function provideGenerate()
{
$data = array();
for ($i = 1; $i < 100; $i += 5) {
$not = str_repeat(chr(0), $i);
$data[] = array($i, $not);
}
return $data;
}
public function testGetStrength()
{
$strength = new Strength(Strength::HIGH);
$actual = Sodium::getStrength();
$this->assertEquals($actual, $strength);
}
/**
* @dataProvider provideGenerate
*/
public function testGenerate($length, $not)
{
if (!extension_loaded('libsodium')) {
$this->markTestSkipped('The libsodium extension is not loaded');
}
$rand = new Sodium();
$stub = $rand->generate($length);
$this->assertEquals($length, strlen($stub));
$this->assertNotEquals($not, $stub);
}
/**
* @dataProvider provideGenerate
*/
public function testGenerateWithoutLibsodium($length, $not)
{
$rand = new Sodium(false);
$stub = $rand->generate($length);
$this->assertEquals($length, strlen($stub));
$this->assertEquals($not, $stub);
}
public function testGenerateWithZeroLength()
{
if (!extension_loaded('libsodium')) {
$this->markTestSkipped('The libsodium extension is not loaded');
}
$rand = new Sodium();
$stub = $rand->generate(0);
$this->assertEquals(0, strlen($stub));
$this->assertEquals('', $stub);
}
public function testGenerateWithZeroLengthWithoutLibsodium()
{
$rand = new Sodium(false);
$stub = $rand->generate(0);
$this->assertEquals(0, strlen($stub));
$this->assertEquals('', $stub);
}
}

View File

@@ -0,0 +1,21 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class URandomTest extends AbstractSourceTest
{
protected static function getExpectedStrength()
{
return new Strength(Strength::HIGH);
}
}

View File

@@ -0,0 +1,21 @@
<?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@@
*/
namespace RandomLib\Source;
use SecurityLib\Strength;
class UniqIDTest extends AbstractSourceTest
{
protected static function getExpectedStrength()
{
return new Strength(Strength::LOW);
}
}

View File

@@ -0,0 +1,168 @@
<?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@@
*/
use RandomLib\Generator;
use RandomLibTest\Mocks\Random\Mixer;
use RandomLibTest\Mocks\Random\Source;
class Vectors_Random_GeneratorTest extends PHPUnit_Framework_TestCase
{
public static function provideGenerateInt()
{
return array(
// First, lets test each offset based range
array(0, 7),
array(0, 15),
array(0, 31),
array(0, 63),
array(0, 127),
array(0, 255),
array(0, 511),
array(0, 1023),
// Let's try a range not starting at 0
array(8, 15),
// Let's try a range with a negative number
array(-18, -11),
// Let's try a non-power-of-2 range
array(10, 100),
// Finally, let's try two large numbers
array(100000, 100007),
array(100000000, 100002047),
// Now, let's force a few loops by setting a valid offset
array(0, 5, 2),
array(0, 9, 5),
array(0, 27, 4),
);
}
public static function provideGenerators()
{
$factory = new \RandomLib\Factory();
$generator = $factory->getLowStrengthGenerator();
$sources = $generator->getSources();
$ret = array();
$ret[] = array(new Generator($sources, new \RandomLib\Mixer\Hash()), 10000, 'hash');
return $ret;
}
/**
* This test asserts that the algorithm that generates the integers does not
* actually introduce any bias into the generated numbers. If this test
* passes, the generated integers from the generator will be as unbiased as
* the sources that provide the data.
*
* @dataProvider provideGenerateInt
*/
public function testGenerateInt($min, $max, $offset = 0)
{
$generator = $this->getGenerator($max - $min + $offset);
for ($i = $max; $i >= $min; $i--) {
$this->assertEquals($i, $generator->generateInt($min, $max));
}
}
/**
* This generator generates two bytes at a time, and uses each 8 bit segment of
* the generated byte as a coordinate on a grid (so 01011010 would be the
* coordinate (0101, 1010) or (5, 10). These are used as inputs to a MonteCarlo
* algorithm for the integral of y=x over a 15x15 grid. The expected answer is
* 1/2 * 15 * 15 (or 1/2 * base * height, since the result is a triangle).
* Therefore, if we get an answer close to that, we know the generator is good.
*
* Now, since the area under the line should be equal to the area above the line.
* Therefore, the ratio of the two areas should be equal. This way, we can avoid
* computing total to figure out the areas.
*
* I have set the bounds on the test to be 80% and 120%. Meaning that I will
* consider the test valid and unbiased if the number of random elements that
* fall under (inside) of the line and the number that fall outside of the line
* are at most 20% apart.
*
* Since testing randomness is not reliable or repeatable, I will only fail the
* test in two different scenarios. The first is if after the iterations the
* outside or the inside is 0. The chances of that happening are so low that
* if it happens, it's relatively safe to assume that something bad happened. The
* second scenario happens when the ratio is outside of the 20% tolerance. If
* that happens, I will re-run the entire test. If that test is outside of the 20%
* tolerance, then the test will fail
*
*
* @dataProvider provideGenerators
*/
public function testGenerate(\RandomLib\Generator $generator, $times)
{
$ratio = $this->doTestGenerate($generator, $times);
if ($ratio < 0.8 || $ratio > 1.2) {
$ratio2 = $this->doTestGenerate($generator, $times);
if ($ratio2 > 1.2 || $ratio2 < 0.8) {
$this->fail(
sprintf(
'The test failed multiple runs with final ratios %f and %f',
$ratio,
$ratio2
)
);
}
}
}
protected function doTestGenerate(\RandomLib\Generator $generator, $times)
{
$inside = 0;
$outside = 0;
$on = 0;
for ($i = 0; $i < $times; $i++) {
$byte = $generator->generate(2);
$byte = unpack('n', $byte);
$byte = array_shift($byte);
$xCoord = ($byte >> 8);
$yCoord = ($byte & 0xFF);
if ($xCoord < $yCoord) {
$outside++;
} elseif ($xCoord == $yCoord) {
$on++;
} else {
$inside++;
}
}
$this->assertGreaterThan(0, $outside, 'Outside Is 0');
$this->assertGreaterThan(0, $inside, 'Inside Is 0');
$ratio = $inside / $outside;
return $ratio;
}
public function getGenerator($random)
{
$source1 = new Source(array(
'generate' => function ($size) use (&$random) {
$ret = pack('N', $random);
$random--;
return substr($ret, -1 * $size);
},
));
$sources = array($source1);
$mixer = new Mixer(array(
'mix'=> function (array $sources) {
if (empty($sources)) {
return '';
}
return array_pop($sources);
},
));
return new Generator($sources, $mixer);
}
}

View File

@@ -0,0 +1,58 @@
<?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@@
*/
/**
* Bootstrap the library. This registers a simple autoloader for autoloading
* classes
*
* If you are using this library inside of another that uses a similar
* autoloading system, you can use that autoloader instead of this file.
*
* PHP version 5.3
*
* @category PHPPasswordLib
* @package test
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @license http://www.gnu.org/licenses/lgpl-2.1.html LGPL v 2.1
*/
namespace RandomLibTest;
ini_set('memory_limit', '1G');
/**
* The simple autoloader for the PasswordLibTest libraries.
*
* This does not use the PRS-0 standards due to the namespace prefix and directory
* structure
*
* @param string $class The class name to load
*
* @return void
*/
spl_autoload_register(function ($class) {
$nslen = strlen(__NAMESPACE__);
if (substr($class, 0, $nslen) != __NAMESPACE__) {
//Only autoload libraries from this package
return;
}
$path = substr(str_replace('\\', '/', $class), $nslen);
$path = __DIR__ . $path . '.php';
if (file_exists($path)) {
require $path;
}
});
define('PATH_ROOT', dirname(__DIR__));
require_once dirname(__DIR__) . '/vendor/autoload.php';