66
77use InvalidArgumentException ;
88use 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 ;
916use 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 ;
1021
1122/**
1223 * Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
3344
3445final readonly class Base64UrlSafe
3546{
36- public static function encode (string $ binString ): string
47+ public static function encode (#[SensitiveParameter] string $ binString ): string
3748 {
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+ }
3856 return static ::doEncode ($ binString , true );
3957 }
4058
41- public static function encodeUnpadded (string $ src ): string
59+ public static function encodeUnpadded (#[SensitiveParameter] string $ src ): string
4260 {
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+ }
4368 return static ::doEncode ($ src , false );
4469 }
4570
46- public static function decode (string $ encodedString , bool $ strictPadding = false ): string
71+ public static function decode (#[SensitiveParameter] string $ encodedString , bool $ strictPadding = false ): string
4772 {
4873 $ srcLen = self ::safeStrlen ($ encodedString );
4974 if ($ srcLen === 0 ) {
@@ -65,6 +90,16 @@ public static function decode(string $encodedString, bool $strictPadding = false
6590 if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
6691 throw new RangeException ('Incorrect padding ' );
6792 }
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+ }
68103 } else {
69104 $ encodedString = rtrim ($ encodedString , '= ' );
70105 $ srcLen = self ::safeStrlen ($ encodedString );
@@ -120,26 +155,21 @@ public static function decode(string $encodedString, bool $strictPadding = false
120155 return $ dest ;
121156 }
122157
123- public static function decodeNoPadding (string $ encodedString ): string
158+ public static function decodeNoPadding (#[SensitiveParameter] string $ encodedString ): string
124159 {
125160 $ srcLen = self ::safeStrlen ($ encodedString );
126161 if ($ srcLen === 0 ) {
127162 return '' ;
128163 }
129164 if (($ srcLen & 3 ) === 0 ) {
130- if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
165+ if ($ encodedString [$ srcLen - 1 ] === '= ' || $ encodedString [ $ srcLen - 2 ] === ' = ' ) {
131166 throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
132167 }
133- if (($ srcLen & 3 ) > 1 ) {
134- if ($ encodedString [$ srcLen - 2 ] === '= ' ) {
135- throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
136- }
137- }
138168 }
139169 return static ::decode ($ encodedString , true );
140170 }
141171
142- private static function doEncode (string $ src , bool $ pad = true ): string
172+ private static function doEncode (#[SensitiveParameter] string $ src , bool $ pad = true ): string
143173 {
144174 $ dest = '' ;
145175 $ srcLen = self ::safeStrlen ($ src );
@@ -204,12 +234,12 @@ private static function encode6Bits(int $src): string
204234 return pack ('C ' , $ src + $ diff );
205235 }
206236
207- private static function safeStrlen (string $ str ): int
237+ private static function safeStrlen (#[SensitiveParameter] string $ str ): int
208238 {
209239 return strlen ($ str );
210240 }
211241
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
213243 {
214244 if ($ length === 0 ) {
215245 return '' ;
0 commit comments