Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions src/Library/Core/Util/Base64UrlSafe.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@

use InvalidArgumentException;
use RangeException;
use SensitiveParameter;
use SodiumException;
use function extension_loaded;
use function pack;
use function rtrim;
use function sodium_base642bin;
use function sodium_bin2base64;
use function strlen;
use function substr;
use function unpack;
use const SODIUM_BASE64_VARIANT_URLSAFE;
use const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING;

/**
* Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
Expand All @@ -33,17 +44,31 @@

final readonly class Base64UrlSafe
{
public static function encode(string $binString): string
public static function encode(#[SensitiveParameter] string $binString): string
{
if (extension_loaded('sodium')) {
try {
return sodium_bin2base64($binString, SODIUM_BASE64_VARIANT_URLSAFE);
} catch (SodiumException $ex) {
throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
}
}
return static::doEncode($binString, true);
}

public static function encodeUnpadded(string $src): string
public static function encodeUnpadded(#[SensitiveParameter] string $src): string
{
if (extension_loaded('sodium')) {
try {
return sodium_bin2base64($src, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
} catch (SodiumException $ex) {
throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
}
}
return static::doEncode($src, false);
}

public static function decode(string $encodedString, bool $strictPadding = false): string
public static function decode(#[SensitiveParameter] string $encodedString, bool $strictPadding = false): string
{
$srcLen = self::safeStrlen($encodedString);
if ($srcLen === 0) {
Expand All @@ -65,6 +90,16 @@ public static function decode(string $encodedString, bool $strictPadding = false
if ($encodedString[$srcLen - 1] === '=') {
throw new RangeException('Incorrect padding');
}
if (extension_loaded('sodium')) {
try {
return sodium_base642bin(
self::safeSubstr($encodedString, 0, $srcLen),
SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
);
} catch (SodiumException $ex) {
throw new RangeException($ex->getMessage(), $ex->getCode(), $ex);
}
}
} else {
$encodedString = rtrim($encodedString, '=');
$srcLen = self::safeStrlen($encodedString);
Expand Down Expand Up @@ -120,26 +155,21 @@ public static function decode(string $encodedString, bool $strictPadding = false
return $dest;
}

public static function decodeNoPadding(string $encodedString): string
public static function decodeNoPadding(#[SensitiveParameter] string $encodedString): string
{
$srcLen = self::safeStrlen($encodedString);
if ($srcLen === 0) {
return '';
}
if (($srcLen & 3) === 0) {
if ($encodedString[$srcLen - 1] === '=') {
if ($encodedString[$srcLen - 1] === '=' || $encodedString[$srcLen - 2] === '=') {
throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding");
}
if (($srcLen & 3) > 1) {
if ($encodedString[$srcLen - 2] === '=') {
throw new InvalidArgumentException("decodeNoPadding() doesn't tolerate padding");
}
}
}
return static::decode($encodedString, true);
}

private static function doEncode(string $src, bool $pad = true): string
private static function doEncode(#[SensitiveParameter] string $src, bool $pad = true): string
{
$dest = '';
$srcLen = self::safeStrlen($src);
Expand Down Expand Up @@ -204,12 +234,12 @@ private static function encode6Bits(int $src): string
return pack('C', $src + $diff);
}

private static function safeStrlen(string $str): int
private static function safeStrlen(#[SensitiveParameter] string $str): int
{
return strlen($str);
}

private static function safeSubstr(string $str, int $start = 0, $length = null): string
private static function safeSubstr(#[SensitiveParameter] string $str, int $start = 0, $length = null): string
{
if ($length === 0) {
return '';
Expand Down
Loading