IDGenerator::generateToken()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

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