Completed
Push — master ( 59dd4d...b5d47e )
by Marwan
15s queued 11s
created

IDGenerator   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 68
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 8
eloc 29
c 1
b 0
f 0
dl 0
loc 68
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A generateToken() 0 17 3
A generateHash() 0 6 1
A generateCryptoSecureRandom() 0 21 4
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 functions for generating unique IDs and Tokens.
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
    public static function generateHash(string $entropy = 'maks-amqp-agent-id'): string
23
    {
24
        $prefix = sprintf('-%s-[%d]-', $entropy, rand());
25
        $symbol = microtime(true) . uniqid($prefix, true);
26
27
        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
    public static function generateToken(int $length = 32, ?string $charset = null, ?string $hashing = null): string
38
    {
39
        $token = '';
40
        $charset = $charset ?? (
41
            implode(range('A', 'Z')) .
42
            implode(range('a', 'z')) .
43
            implode(range(0, 9))
44
        );
45
        $max = strlen($charset);
46
47
        for ($i = 0; $i < $length; $i++) {
48
            $token .= $charset[
49
                self::generateCryptoSecureRandom(0, $max - 1)
50
            ];
51
        }
52
53
        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
    protected static function generateCryptoSecureRandom(int $min, int $max): int
63
    {
64
        $range = $max - $min;
65
        if ($range < 1) {
66
            return $min;
67
        }
68
69
        $log = ceil(log($range, 2));
70
        $bytes = (int)(($log / 8) + 1); // length in bytes
71
        $bits = (int)($log + 1); // length in bits
72
        $filter = (int)((1 << $bits) - 1); // set all lower bits to 1
73
74
        do {
75
            $random = PHP_VERSION >= 7
76
                ? random_bytes($bytes)
77
                : openssl_random_pseudo_bytes($bytes);
78
            $random = hexdec(bin2hex($random));
79
            $random = $random & $filter; // discard irrelevant bits
80
        } while ($random > $range);
81
82
        return $min + $random;
83
    }
84
}
85