66
77use InvalidArgumentException ;
88use RangeException ;
9+ use SensitiveParameter ;
10+ use SodiumException ;
11+ use function extension_loaded ;
12+ use function pack ;
13+ use function rtrim ;
914use function strlen ;
15+ use function substr ;
16+ use function unpack ;
17+ use function sodium_base642bin ;
18+ use function sodium_bin2base64 ;
19+ use const SODIUM_BASE64_VARIANT_URLSAFE ;
20+ use const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING ;
1021
1122/**
1223 * Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
3344
3445final readonly class Base64UrlSafe
3546{
36- public static function encode (string $ binString ): string
37- {
47+ public static function encode (
48+ #[SensitiveParameter]
49+ string $ binString
50+ ): string {
51+ if (extension_loaded ('sodium ' )) {
52+ try {
53+ return sodium_bin2base64 ($ binString , SODIUM_BASE64_VARIANT_URLSAFE );
54+ } catch (SodiumException $ ex ) {
55+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
56+ }
57+ }
3858 return static ::doEncode ($ binString , true );
3959 }
4060
41- public static function encodeUnpadded (string $ src ): string
42- {
61+ public static function encodeUnpadded (
62+ #[SensitiveParameter]
63+ string $ src
64+ ): string {
65+ if (extension_loaded ('sodium ' )) {
66+ try {
67+ return sodium_bin2base64 ($ src , SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING );
68+ } catch (SodiumException $ ex ) {
69+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
70+ }
71+ }
4372 return static ::doEncode ($ src , false );
4473 }
4574
46- public static function decode (string $ encodedString , bool $ strictPadding = false ): string
47- {
75+ public static function decode (
76+ #[SensitiveParameter]
77+ string $ encodedString ,
78+ bool $ strictPadding = false
79+ ): string {
4880 $ srcLen = self ::safeStrlen ($ encodedString );
4981 if ($ srcLen === 0 ) {
5082 return '' ;
@@ -65,6 +97,13 @@ public static function decode(string $encodedString, bool $strictPadding = false
6597 if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
6698 throw new RangeException ('Incorrect padding ' );
6799 }
100+ if (extension_loaded ('sodium ' )) {
101+ try {
102+ return sodium_base642bin (self ::safeSubstr ($ encodedString , 0 , $ srcLen ), SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING );
103+ } catch (SodiumException $ ex ) {
104+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
105+ }
106+ }
68107 } else {
69108 $ encodedString = rtrim ($ encodedString , '= ' );
70109 $ srcLen = self ::safeStrlen ($ encodedString );
@@ -120,27 +159,27 @@ public static function decode(string $encodedString, bool $strictPadding = false
120159 return $ dest ;
121160 }
122161
123- public static function decodeNoPadding (string $ encodedString ): string
124- {
162+ public static function decodeNoPadding (
163+ #[SensitiveParameter]
164+ string $ encodedString
165+ ): string {
125166 $ srcLen = self ::safeStrlen ($ encodedString );
126167 if ($ srcLen === 0 ) {
127168 return '' ;
128169 }
129170 if (($ srcLen & 3 ) === 0 ) {
130- if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
171+ if ($ encodedString [$ srcLen - 1 ] === '= ' || $ encodedString [ $ srcLen - 2 ] === ' = ' ) {
131172 throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
132173 }
133- if (($ srcLen & 3 ) > 1 ) {
134- if ($ encodedString [$ srcLen - 2 ] === '= ' ) {
135- throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
136- }
137- }
138174 }
139175 return static ::decode ($ encodedString , true );
140176 }
141177
142- private static function doEncode (string $ src , bool $ pad = true ): string
143- {
178+ private static function doEncode (
179+ #[SensitiveParameter]
180+ string $ src ,
181+ bool $ pad = true
182+ ): string {
144183 $ dest = '' ;
145184 $ srcLen = self ::safeStrlen ($ src );
146185 for ($ i = 0 ; $ i + 3 <= $ srcLen ; $ i += 3 ) {
@@ -204,13 +243,19 @@ private static function encode6Bits(int $src): string
204243 return pack ('C ' , $ src + $ diff );
205244 }
206245
207- private static function safeStrlen (string $ str ): int
208- {
246+ private static function safeStrlen (
247+ #[SensitiveParameter]
248+ string $ str
249+ ): int {
209250 return strlen ($ str );
210251 }
211252
212- private static function safeSubstr (string $ str , int $ start = 0 , $ length = null ): string
213- {
253+ private static function safeSubstr (
254+ #[SensitiveParameter]
255+ string $ str ,
256+ int $ start = 0 ,
257+ $ length = null
258+ ): string {
214259 if ($ length === 0 ) {
215260 return '' ;
216261 }
0 commit comments