PseudoRandomStringGenerator::generate()   B
last analyzed

Complexity

Conditions 7
Paths 10

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 19
c 1
b 0
f 0
dl 0
loc 29
rs 8.8333
cc 7
nc 10
nop 1
1
<?php
2
3
/**
4
 * PHP version 5.4 and 8
5
 *
6
 * @category  Core
7
 * @package   Payever\Core
8
 * @author    payever GmbH <[email protected]>
9
 * @author    Hennadii.Shymanskyi <[email protected]>
10
 * @copyright 2017-2021 payever GmbH
11
 * @license   MIT <https://opensource.org/licenses/MIT>
12
 * @link      https://docs.payever.org/shopsystems/api/getting-started
13
 */
14
15
namespace Payever\ExternalIntegration\Core;
16
17
/**
18
 * @SuppressWarnings(PHPMD.MissingImport)
19
 */
20
class PseudoRandomStringGenerator
21
{
22
    /** @var string */
23
    protected static $fallbackKeyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
24
25
    /**
26
     * Generates a random string, using a cryptographically secure pseudo-random number generator.
27
     * Falling back to non-CSPRNG generation when no source of random available.
28
     *
29
     * @param int $length
30
     *
31
     * @return string
32
     *
33
     * @throws \Exception when CSPRNG source failed to provide random bytes
34
     * @SuppressWarnings(PHPMD.IfStatementAssignment)
35
     * @SuppressWarnings(PHPMD.ElseExpression)
36
     */
37
    public function generate($length = 64)
38
    {
39
        if (function_exists('random_bytes')) {
40
            $binaryString = random_bytes($length);
41
        // @codeCoverageIgnoreStart
42
        } elseif (function_exists('mcrypt_create_iv')) {
43
            $binaryString = /** @scrutinizer ignore-deprecated */ mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
44
        } elseif (function_exists('openssl_random_pseudo_bytes')) {
45
            $binaryString = openssl_random_pseudo_bytes($length);
46
        } elseif (($stream = fopen('/dev/urandom', 'rb'))) {
47
            stream_set_read_buffer($stream, 0);
48
            $binaryString = fread($stream, $length);
49
            fclose($stream);
50
        } else {
51
            // well, we've tried
52
            $chain = '';
53
            $max = mb_strlen(static::$fallbackKeyspace, '8bit') - 1;
54
            for ($i = 0; $i < $length; ++$i) {
55
                $chain .= static::$fallbackKeyspace[rand(0, $max)];
56
            }
57
            $binaryString = hex2bin($chain);
58
        }
59
60
        if ($binaryString === false) {
61
            throw new \RuntimeException('Unable to generate random string.');
62
        }
63
        // @codeCoverageIgnoreEnd
64
65
        return $this->binToHex($binaryString, $length);
66
    }
67
68
    /**
69
     * @param string $binaryData
70
     * @param int $length
71
     *
72
     * @return bool|string
73
     */
74
    protected function binToHex($binaryData, $length)
75
    {
76
        return substr(bin2hex($binaryData), 0, $length);
77
    }
78
}
79