6
6
7
7
use InvalidArgumentException ;
8
8
use RangeException ;
9
+ use SensitiveParameter ;
10
+ use SodiumException ;
11
+ use function extension_loaded ;
12
+ use function pack ;
13
+ use function rtrim ;
14
+ use function sodium_base642bin ;
15
+ use function sodium_bin2base64 ;
9
16
use function strlen ;
17
+ use function substr ;
18
+ use function unpack ;
19
+ use const SODIUM_BASE64_VARIANT_URLSAFE ;
20
+ use const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING ;
10
21
11
22
/**
12
23
* Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
33
44
34
45
final readonly class Base64UrlSafe
35
46
{
36
- public static function encode (string $ binString ): string
47
+ public static function encode (#[SensitiveParameter] string $ binString ): string
37
48
{
49
+ if (extension_loaded ('sodium ' )) {
50
+ try {
51
+ return sodium_bin2base64 ($ binString , SODIUM_BASE64_VARIANT_URLSAFE );
52
+ } catch (SodiumException $ ex ) {
53
+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
54
+ }
55
+ }
38
56
return static ::doEncode ($ binString , true );
39
57
}
40
58
41
- public static function encodeUnpadded (string $ src ): string
59
+ public static function encodeUnpadded (#[SensitiveParameter] string $ src ): string
42
60
{
61
+ if (extension_loaded ('sodium ' )) {
62
+ try {
63
+ return sodium_bin2base64 ($ src , SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING );
64
+ } catch (SodiumException $ ex ) {
65
+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
66
+ }
67
+ }
43
68
return static ::doEncode ($ src , false );
44
69
}
45
70
46
- public static function decode (string $ encodedString , bool $ strictPadding = false ): string
71
+ public static function decode (#[SensitiveParameter] string $ encodedString , bool $ strictPadding = false ): string
47
72
{
48
73
$ srcLen = self ::safeStrlen ($ encodedString );
49
74
if ($ srcLen === 0 ) {
@@ -65,6 +90,16 @@ public static function decode(string $encodedString, bool $strictPadding = false
65
90
if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
66
91
throw new RangeException ('Incorrect padding ' );
67
92
}
93
+ if (extension_loaded ('sodium ' )) {
94
+ try {
95
+ return sodium_base642bin (
96
+ self ::safeSubstr ($ encodedString , 0 , $ srcLen ),
97
+ SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
98
+ );
99
+ } catch (SodiumException $ ex ) {
100
+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
101
+ }
102
+ }
68
103
} else {
69
104
$ encodedString = rtrim ($ encodedString , '= ' );
70
105
$ srcLen = self ::safeStrlen ($ encodedString );
@@ -120,26 +155,21 @@ public static function decode(string $encodedString, bool $strictPadding = false
120
155
return $ dest ;
121
156
}
122
157
123
- public static function decodeNoPadding (string $ encodedString ): string
158
+ public static function decodeNoPadding (#[SensitiveParameter] string $ encodedString ): string
124
159
{
125
160
$ srcLen = self ::safeStrlen ($ encodedString );
126
161
if ($ srcLen === 0 ) {
127
162
return '' ;
128
163
}
129
164
if (($ srcLen & 3 ) === 0 ) {
130
- if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
165
+ if ($ encodedString [$ srcLen - 1 ] === '= ' || $ encodedString [ $ srcLen - 2 ] === ' = ' ) {
131
166
throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
132
167
}
133
- if (($ srcLen & 3 ) > 1 ) {
134
- if ($ encodedString [$ srcLen - 2 ] === '= ' ) {
135
- throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
136
- }
137
- }
138
168
}
139
169
return static ::decode ($ encodedString , true );
140
170
}
141
171
142
- private static function doEncode (string $ src , bool $ pad = true ): string
172
+ private static function doEncode (#[SensitiveParameter] string $ src , bool $ pad = true ): string
143
173
{
144
174
$ dest = '' ;
145
175
$ srcLen = self ::safeStrlen ($ src );
@@ -204,12 +234,12 @@ private static function encode6Bits(int $src): string
204
234
return pack ('C ' , $ src + $ diff );
205
235
}
206
236
207
- private static function safeStrlen (string $ str ): int
237
+ private static function safeStrlen (#[SensitiveParameter] string $ str ): int
208
238
{
209
239
return strlen ($ str );
210
240
}
211
241
212
- private static function safeSubstr (string $ str , int $ start = 0 , $ length = null ): string
242
+ private static function safeSubstr (#[SensitiveParameter] string $ str , int $ start = 0 , $ length = null ): string
213
243
{
214
244
if ($ length === 0 ) {
215
245
return '' ;
0 commit comments