Completed
Push — master ( 4ba8ef...d71f88 )
by Michael
01:42
created

Random::toss()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * Random.php
5
 * 
6
 * PHP version 5
7
 * 
8
 * @category Dcrypt
9
 * @package  Dcrypt
10
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
11
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
12
 * @link     https://github.com/mmeyer2k/dcrypt
13
 * @link     https://apigen.ci/github/mmeyer2k/dcrypt
14
 */
15
16
namespace Dcrypt;
17
18
/**
19
 * Fail-safe wrapper for mcrypt_create_iv (preferably) and
20
 * openssl_random_pseudo_bytes (fallback).
21
 *
22
 * @category Dcrypt
23
 * @package  Dcrypt
24
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
25
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
26
 * @link     https://github.com/mmeyer2k/dcrypt
27
 * @link     https://apigen.ci/github/mmeyer2k/dcrypt/class-Dcrypt.Random.html
28
 */
29
final class Random
30
{
31
    /**
32
     * Get random bytes from Mcrypt
33
     * 
34
     * @param int $bytes Number of bytes to get
35
     * 
36
     * @return string
37
     */
38 19
    private static function fromMcrypt($bytes)
39
    {
40 19
        $ret = \mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
41
42 19
        if ($ret === false) {
43
            self::toss(); // @codeCoverageIgnore
44
        }
45
46 19
        return $ret;
47
    }
48
49
    /**
50
     * Return securely generated random bytes.
51
     * 
52
     * @param int  $bytes  Number of bytes to get
53
     * 
54
     * @return string
55
     */
56 19
    public static function bytes($bytes)
57
    {
58 19
        if (\function_exists('random_bytes')) {
59
            return \random_bytes($bytes);
60 19
        } elseif (\function_exists('mcrypt_create_iv')) {
61 19
            return self::fromMcrypt($bytes);
62
        }
63
        
64
        self::toss(); // @codeCoverageIgnore
65
    }
66
67
    /**
68
     * Throw an error when a failure occurs.
69
     * 
70
     * @codeCoverageIgnore
71
     */
72
    private static function toss()
73
    {
74
        $e = 'Dcrypt failed to generate a random number';
75
        throw new \exception($e);
76
    }
77
    
78
    /**
79
     * Deterministic seeded array shuffle function.
80
     *
81
     * @param array  $array
82
     * @param string $seed
83
     * @param int    $mode
84
     * 
85
     * @return array
86
     */
87
    public static function shuffle($array, $seed, $mode = MT_RAND_PHP)
88
    {
89
        $count = count($array);
90
91
        $range = range(0, count($array) - 1);
92
93
        // Hash the seed and extract bytes to make integer with
94
        $seed = substr(hash('sha256', $seed, true), 0, PHP_INT_SIZE);
95
96
        // Convert bytes to int
97
        $seed = unpack("L", $seed);
98
99
        mt_srand($seed[1], $mode);
100
101
        foreach ($range as $a) {
102
            $b = mt_rand(0, $count - 1);
103
104
            $v = $array[$a];
105
106
            $array[$a] = $array[$b];
107
108
            $array[$b] = $v;
109
        }
110
111
        return $array;
112
    }
113
}
114