Skip to content

Commit ce138fc

Browse files
committed
Improve Base64UrlSafe performance when ext-sodium is installed
These adjustments are only applying the changes made in paragonie/constant_time_encoding between 2.6.3 and 2.8.2 See: https://github.com/paragonie/constant_time_encoding/compare/v2.6.3..v2.8.2
1 parent 795bb30 commit ce138fc

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

src/Library/Core/Util/Base64UrlSafe.php

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@
66

77
use InvalidArgumentException;
88
use RangeException;
9+
use SensitiveParameter;
10+
use SodiumException;
11+
use function extension_loaded;
12+
use function pack;
13+
use function rtrim;
914
use 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.
@@ -33,18 +44,39 @@
3344

3445
final 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

Comments
 (0)