Completed
Push — master ( b97a32...b04b1c )
by Antonio Carlos
02:42
created

Base32::strPadBase32()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
3
namespace PragmaRX\Google2FA\Support;
4
5
use ParagonIE\ConstantTime\Base32 as ParagonieBase32;
6
use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException;
7
// use PragmaRX\Google2FA\Exceptions\InvalidCharactersException;
8
trait Base32
9
{
10
    /**
11
     * Enforce Google Authenticator compatibility.
12
     */
13
    protected $enforceGoogleAuthenticatorCompatibility = true;
14
15
    /**
16
     * Generate a digit secret key in base32 format.
17
     *
18
     * @param int $length
19
     *
20
     * @return string
21
     */
22
    public function generateBase32RandomKey($length = 16, $prefix = '')
23
    {
24
        $secret = $prefix ? $this->toBase32($prefix) : '';
25
26
        $secret = $this->strPadBase32($secret, $length);
27
28
        $this->validateSecret($secret);
29
30
        return $secret;
31
    }
32
33
    /**
34
     * Decodes a base32 string into a binary string.
35
     *
36
     * @param string $b32
37
     *
38
     * @throws InvalidCharactersException
39
     *
40
     * @return int
41
     */
42
    public function base32Decode($b32)
43
    {
44
        $b32 = strtoupper($b32);
45
46
        $this->validateSecret($b32);
47
48
        return ParagonieBase32::decodeUpper($b32);
49
    }
50
51
    /**
52
     * Pad string with random base 32 chars.
53
     *
54
     * @param $string
55
     * @param $length
56
     * @return string
57
     */
58
    private function strPadBase32($string, $length)
59
    {
60
        for ($i = 0; $i < $length; $i++) {
61
            $string .= Constants::VALID_FOR_B32_SCRAMBLED[ $this->getRandomNumber() ];
62
        }
63
64
        return $string;
65
    }
66
67
    /**
68
     * Encode a string to Base32.
69
     *
70
     * @param $string
71
     *
72
     * @return mixed
73
     */
74
    public function toBase32($string)
75
    {
76
        $encoded = ParagonieBase32::encodeUpper($string);
77
78
        return str_replace('=', '', $encoded);
79
    }
80
81
    /**
82
     * Get a random number.
83
     *
84
     * @param $from
85
     * @param $to
86
     *
87
     * @return int
88
     */
89
    protected function getRandomNumber($from = 0, $to = 31)
90
    {
91
        return random_int($from, $to);
92
    }
93
94
    /**
95
     * Validate the secret.
96
     *
97
     * @param $b32
98
     */
99
    protected function validateSecret($b32)
100
    {
101
        $this->checkForValidCharacters($b32);
102
103
        $this->checkGoogleAuthenticatorCompatibility($b32);
104
    }
105
106
    /**
107
     * Check if the secret key is compatible with Google Authenticator.
108
     *
109
     * @param $b32
110
     *
111
     * @throws IncompatibleWithGoogleAuthenticatorException
112
     */
113
    protected function checkGoogleAuthenticatorCompatibility($b32)
114
    {
115
        if ($this->enforceGoogleAuthenticatorCompatibility && ((strlen($b32) & (strlen($b32) - 1)) !== 0)) {
116
            throw new IncompatibleWithGoogleAuthenticatorException();
117
        }
118
    }
119
120
    /**
121
     * Check if all secret key characters are valid.
122
     *
123
     * @param $b32
124
     *
125
     * @throws InvalidCharactersException
126
     */
127
    protected function checkForValidCharacters($b32)
128
    {
129
        if (!preg_match('/^['.Constants::VALID_FOR_B32.']+$/', $b32, $match)) {
130
            throw new InvalidCharactersException();
131
        }
132
    }
133
}
134