ThreemaGateway_Helper_Random::canUseLibsodium()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 0
1
<?php
2
/**
3
 * Creates random data, strings, numbers etc.
4
 *
5
 * It makes use of libsodium >= 0.2.0 if possible.
6
 *
7
 * @package ThreemaGateway
8
 * @author rugk
9
 * @copyright Copyright (c) 2016 rugk
10
 * @license MIT
11
 */
12
13
class ThreemaGateway_Helper_Random
14
{
15
    /**
16
     * Generates a random numeric string.
17
     *
18
     * @param  int    $length The length of the string
19
     * @return string
20
     */
21
    public static function getRandomNumeric($length)
22
    {
23
        return self::getRandomString($length, '0123456789');
24
    }
25
26
    /**
27
     * Generates a random alphabetic string. (only lower letters).
28
     *
29
     * @param  int    $length The length of the string
30
     * @return string
31
     */
32
    public static function getRandomAlpha($length)
33
    {
34
        return self::getRandomString($length, 'abcdefghijklmnopqrstuvwxyz');
35
    }
36
37
    /**
38
     * Generates a random alphanumeric string. (only lower letters).
39
     *
40
     * This excludes letters which are commonly confused such as O and 0.
41
     *
42
     * @param  int    $length The length of the string
43
     * @return string
44
     */
45
    public static function getRandomAlphaNum($length)
46
    {
47
        return self::getRandomString($length, 'abcdefghjkmnpqrstuvwxyz0123456789');
48
    }
49
50
    /**
51
     * Generates a random string.
52
     *
53
     * Note that they $keyspace parameter may be ignored if libsodium is not
54
     * available as XenForo's native method has a hardcoded keyspace.
55
     *
56
     * @link https://paragonie.com/blog/2015/07/how-safely-generate-random-strings-and-integers-in-php
57
     * @param  int    $length   The length of the string
58
     * @param  string $keyspace The characters to choose from
59
     * @return string
60
     */
61
    public static function getRandomString($length, $keyspace = 'abcdefghijklmnopqrstuvwxyz01234567')
62
    {
63
        /** @var string $output */
64
        $output = '';
65
        if (self::canUseLibsodium()) {
66
            /** @var int $keysize */
67
            $keysize = strlen($keyspace);
68
69
            try {
70
                for ($i = 0; $i < $length; ++$i) {
71
                    $output .= $keyspace[self::getRandomInteger($keysize)];
72
                }
73
            } catch (Exception $e) {
74
                $output = '';
75
            }
76
        }
77
78
        if (!$output) {
79
            $output = XenForo_Application::generateRandomString($length, false);
80
        }
81
82
        return $output;
83
    }
84
85
    /**
86
     * Generates some random bytes.
87
     *
88
     * @link https://paragonie.com/book/pecl-libsodium/read/02-random-data.md
89
     * @param  int    $number Number of bytes to return
90
     * @return string
91
     */
92
    public static function getRandomBytes($number)
93
    {
94
        /** @var string $output */
95
        $output = '';
96
97
        if (self::canUseLibsodium()) {
98
            try {
99
                $output = \Sodium\randombytes_buf($number);
100
            } catch (Exception $e) {
101
                $output = '';
102
            }
103
        }
104
105
        if (!$output) {
106
            // recent XenForo versions (>= 1.5.11) do it better than Salt,
107
            // so only use Salt as a fallback if the XenForo version is older
108
            if (XenForo_Application::$versionId < 1051100) {
109
                // try PHP SDK, fails if not yet available
110
                try {
111
                    $output = ThreemaGateway_Handler_PhpSdk::getInstance()->getCryptTool()->createRandom($number);
112
                } catch (Exception $e) {
113
                    $output = '';
114
                }
115
            }
116
        }
117
118
        // use XenForo's native method as the last fallback
119
        if (!$output) {
120
            $output = XenForo_Application::generateRandomString($number, true);
121
        }
122
123
        return $output;
124
    }
125
126
    /**
127
     * Generates some random integers.
128
     *
129
     * IMPORTANT: This required Libsodium >= 0.2.0. If libsodium is not
130
     * installed
131
     *
132
     * @link https://paragonie.com/book/pecl-libsodium/read/02-random-data.md
133
     * @param  int               $range Upper bound
134
     * @throws XenForo_Exception
135
     * @return int
136
     */
137
    public static function getRandomInteger($range)
138
    {
139
        self::assertLibsodiumAvailable();
140
141
        return \Sodium\randombytes_uniform($range);
142
    }
143
144
    /**
145
     * Tests whether the libsodium library can be used.
146
     *
147
     * @throws XenForo_Exception
148
     */
149
    protected static function assertLibsodiumAvailable()
150
    {
151
        if (!self::canUseLibsodium()) {
152
            throw new XenForo_Exception(new XenForo_Phrase('threemagw_libsodium_error'));
153
        }
154
    }
155
156
    /**
157
     * Tests whether the libsodium library can be used.
158
     *
159
     * @return bool
160
     */
161
    protected static function canUseLibsodium()
162
    {
163
        return extension_loaded('libsodium') && !method_exists('Sodium', 'sodium_version_string');
164
    }
165
}
166