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,13 @@ 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 (self ::safeSubstr ($ encodedString , 0 , $ srcLen ), SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING );
96+ } catch (SodiumException $ ex ) {
97+ throw new RangeException ($ ex ->getMessage (), $ ex ->getCode (), $ ex );
98+ }
99+ }
68100 } else {
69101 $ encodedString = rtrim ($ encodedString , '= ' );
70102 $ srcLen = self ::safeStrlen ($ encodedString );
@@ -120,26 +152,21 @@ public static function decode(string $encodedString, bool $strictPadding = false
120152 return $ dest ;
121153 }
122154
123- public static function decodeNoPadding (string $ encodedString ): string
155+ public static function decodeNoPadding (#[SensitiveParameter] string $ encodedString ): string
124156 {
125157 $ srcLen = self ::safeStrlen ($ encodedString );
126158 if ($ srcLen === 0 ) {
127159 return '' ;
128160 }
129161 if (($ srcLen & 3 ) === 0 ) {
130- if ($ encodedString [$ srcLen - 1 ] === '= ' ) {
162+ if ($ encodedString [$ srcLen - 1 ] === '= ' || $ encodedString [ $ srcLen - 2 ] === ' = ' ) {
131163 throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
132164 }
133- if (($ srcLen & 3 ) > 1 ) {
134- if ($ encodedString [$ srcLen - 2 ] === '= ' ) {
135- throw new InvalidArgumentException ("decodeNoPadding() doesn't tolerate padding " );
136- }
137- }
138165 }
139166 return static ::decode ($ encodedString , true );
140167 }
141168
142- private static function doEncode (string $ src , bool $ pad = true ): string
169+ private static function doEncode (#[SensitiveParameter] string $ src , bool $ pad = true ): string
143170 {
144171 $ dest = '' ;
145172 $ srcLen = self ::safeStrlen ($ src );
@@ -204,12 +231,12 @@ private static function encode6Bits(int $src): string
204231 return pack ('C ' , $ src + $ diff );
205232 }
206233
207- private static function safeStrlen (string $ str ): int
234+ private static function safeStrlen (#[SensitiveParameter] string $ str ): int
208235 {
209236 return strlen ($ str );
210237 }
211238
212- private static function safeSubstr (string $ str , int $ start = 0 , $ length = null ): string
239+ private static function safeSubstr (#[SensitiveParameter] string $ str , int $ start = 0 , $ length = null ): string
213240 {
214241 if ($ length === 0 ) {
215242 return '' ;
0 commit comments