Completed
Branch dev (b63562)
by Marwan
01:48
created

IDGenerator::generateHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * @author Marwan Al-Soltany <[email protected]>
4
 * @copyright Marwan Al-Soltany 2020
5
 * For the full copyright and license information, please view
6
 * the LICENSE file that was distributed with this source code.
7
 */
8
9
namespace MAKS\AmqpAgent\Helper;
10
11
/**
12
 * A class containing miscellaneous helper functions.
13
 * @since 2.0.0
14
 */
15
final class IDGenerator
16
{
17
    /**
18
     * Generates an md5 hash from microtime and uniqid.
19
     * @param string $entropy [optional] Additional entropy.
20
     * @return string
21
     */
22 4
    public static function generateHash(string $entropy = 'maks-amqp-agent-id'): string
23
    {
24 4
        $prefix = sprintf('-%s-[%d]-', $entropy, rand());
25 4
        $symbol = microtime(true) . uniqid($prefix, true);
26
27 4
        return md5($symbol);
28
    }
29
30
    /**
31
     * Generates a crypto safe unique token. Note that this function is pretty expensive.
32
     * @param int $length The length of the token. If the token is hashed this will not be the length of the returned string.
33
     * @param string $charset [optional] A string of characters to generate the token from. Defaults to alphanumeric.
34
     * @param string $hashing [optional] A name of hashing algorithm to hash the generated token with. Defaults to no hashing.
35
     * @return string
36
     */
37 2
    public static function generateToken(int $length = 32, ?string $charset = null, ?string $hashing = null): string
38
    {
39 2
        $token = '';
40 2
        $charset = $charset ?? (
41 2
            implode(range('A', 'Z')) .
42 2
            implode(range('a', 'z')) .
43 2
            implode(range(0, 9))
44
        );
45 2
        $max = strlen($charset);
46
47 2
        for ($i = 0; $i < $length; $i++) {
48
            $token .= $charset[
49 2
                self::generateCryptoSecureRandom(0, $max - 1)
50
            ];
51
        }
52
53 2
        return $hashing ? hash($hashing, $token) : $token;
54
    }
55
56
    /**
57
     * Generates a crypto secure random number.
58
     * @param int $min
59
     * @param int $max
60
     * @return int
61
     */
62 2
    protected static function generateCryptoSecureRandom(int $min, int $max): int
63
    {
64 2
        $range = $max - $min;
65 2
        if ($range < 1) {
66 1
            return $min;
67
        }
68
69 2
        $log = ceil(log($range, 2));
70 2
        $bytes = (int)(($log / 8) + 1); // length in bytes
71 2
        $bits = (int)($log + 1); // length in bits
72 2
        $filter = (int)((1 << $bits) - 1); // set all lower bits to 1
73
74
        do {
75 2
            $random = PHP_VERSION >= 7
76 2
                ? random_bytes($bytes)
77 2
                : openssl_random_pseudo_bytes($bytes);
78 2
            $random = hexdec(bin2hex($random));
79 2
            $random = $random & $filter; // discard irrelevant bits
80 2
        } while ($random > $range);
81
82 2
        return $min + $random;
83
    }
84
}
85