diff --git a/phpseclib/Common/Functions/Strings.php b/phpseclib/Common/Functions/Strings.php index 9a424194..0f446142 100644 --- a/phpseclib/Common/Functions/Strings.php +++ b/phpseclib/Common/Functions/Strings.php @@ -17,6 +17,7 @@ namespace phpseclib3\Common\Functions; use ParagonIE\ConstantTime\Base64; use ParagonIE\ConstantTime\Base64UrlSafe; +use ParagonIE\ConstantTime\Hex; use phpseclib3\Math\BigInteger; use phpseclib3\Math\Common\FiniteField; @@ -446,4 +447,30 @@ abstract class Strings sodium_bin2base64($data, SODIUM_BASE64_VARIANT_URLSAFE) : Base64::encode($data); } + + /** + * Constant Time Hex Decoder + * + * @param string $data + * @return string + */ + public static function hex2bin($data) + { + return function_exists('sodium_hex2bin') ? + sodium_hex2bin($data) : + Hex::decode($data); + } + + /** + * Constant Time Hex Encoder + * + * @param string $data + * @return string + */ + public static function bin2hex($data) + { + return function_exists('sodium_bin2hex') ? + sodium_bin2hex($data) : + Hex::encode($data); + } } diff --git a/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php b/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php index 6e431022..4d9808ae 100644 --- a/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php +++ b/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace phpseclib3\Crypt\Common\Formats\Keys; -use ParagonIE\ConstantTime\Hex; use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\AES; use phpseclib3\Crypt\DES; @@ -129,7 +128,7 @@ abstract class PKCS1 extends PKCS * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { - $iv = Hex::decode(trim($matches[2])); + $iv = Strings::hex2bin(trim($matches[2])); // remove the Proc-Type / DEK-Info sections as they're no longer needed $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); $ciphertext = ASN1::extractBER($key); @@ -174,7 +173,7 @@ abstract class PKCS1 extends PKCS $iv = Random::string($cipher->getBlockLength() >> 3); $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3)); $cipher->setIV($iv); - $iv = strtoupper(Hex::encode($iv)); + $iv = strtoupper(Strings::bin2hex($iv)); return "-----BEGIN $type PRIVATE KEY-----\r\n" . "Proc-Type: 4,ENCRYPTED\r\n" . "DEK-Info: " . $encryptionAlgorithm . ",$iv\r\n" . diff --git a/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php b/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php index 17e3f9ed..8d49ce13 100644 --- a/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php +++ b/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php @@ -17,7 +17,6 @@ declare(strict_types=1); namespace phpseclib3\Crypt\Common\Formats\Keys; -use ParagonIE\ConstantTime\Hex; use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\AES; use phpseclib3\Crypt\Hash; @@ -73,7 +72,7 @@ abstract class PuTTY $sequence = 0; while (strlen($symkey) < $length) { $temp = pack('Na*', $sequence++, $password); - $symkey .= Hex::decode(sha1($temp)); + $symkey .= Strings::hex2bin(sha1($temp)); } return substr($symkey, 0, $length); } @@ -213,7 +212,7 @@ abstract class PuTTY $memory = trim(preg_replace('#Argon2-Memory: (\d+)#', '$1', $key[$offset++])); $passes = trim(preg_replace('#Argon2-Passes: (\d+)#', '$1', $key[$offset++])); $parallelism = trim(preg_replace('#Argon2-Parallelism: (\d+)#', '$1', $key[$offset++])); - $salt = Hex::decode(trim(preg_replace('#Argon2-Salt: ([0-9a-f]+)#', '$1', $key[$offset++]))); + $salt = Strings::hex2bin(trim(preg_replace('#Argon2-Salt: ([0-9a-f]+)#', '$1', $key[$offset++]))); extract(self::generateV3Key($password, $flavour, (int)$memory, (int)$passes, $salt)); @@ -248,7 +247,7 @@ abstract class PuTTY $source .= Strings::packSSH2('s', $private); $hmac = trim(preg_replace('#Private-MAC: (.+)#', '$1', $key[$offset + $privateLength])); - $hmac = Hex::decode($hmac); + $hmac = Strings::hex2bin($hmac); if (!hash_equals($hash->hash($source), $hmac)) { throw new \UnexpectedValueException('MAC validation error'); @@ -306,7 +305,7 @@ abstract class PuTTY $key .= "Argon2-Memory: 8192\r\n"; $key .= "Argon2-Passes: 13\r\n"; $key .= "Argon2-Parallelism: 1\r\n"; - $key .= "Argon2-Salt: " . Hex::encode($salt) . "\r\n"; + $key .= "Argon2-Salt: " . Strings::bin2hex($salt) . "\r\n"; extract(self::generateV3Key($password, 'Argon2id', 8192, 13, $salt)); $hash = new Hash('sha256'); @@ -332,7 +331,7 @@ abstract class PuTTY $private = Strings::base64_encode($private); $key .= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; $key .= chunk_split($private, 64); - $key .= 'Private-MAC: ' . Hex::encode($hash->hash($source)) . "\r\n"; + $key .= 'Private-MAC: ' . Strings::bin2hex($hash->hash($source)) . "\r\n"; return $key; } diff --git a/phpseclib/Crypt/EC/Formats/Keys/Common.php b/phpseclib/Crypt/EC/Formats/Keys/Common.php index 0489263e..b2130651 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/Common.php +++ b/phpseclib/Crypt/EC/Formats/Keys/Common.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace phpseclib3\Crypt\EC\Formats\Keys; -use ParagonIE\ConstantTime\Hex; use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve; @@ -249,8 +248,8 @@ trait Common $curve->setModulo(...$modulo); $len = ceil($modulo[0] / 8); $curve->setCoefficients( - Hex::encode($data['curve']['a']), - Hex::encode($data['curve']['b']) + Strings::bin2hex($data['curve']['a']), + Strings::bin2hex($data['curve']['b']) ); $point = self::extractPoint("\0" . $data['base'], $curve); $curve->setBasePoint(...$point); @@ -294,7 +293,7 @@ trait Common // the first byte of a bit string represents the number of bits in the last byte that are to be ignored but, // currently, bit strings wanting a non-zero amount of bits trimmed are not supported if (($val = Strings::shift($str)) != "\0") { - throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Hex::encode($val)); + throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Strings::bin2hex($val)); } if ($str == "\0") { return []; @@ -312,7 +311,7 @@ trait Common preg_match("#(.)(.{{$order}})(.{{$order}})#s", $str, $matches); [, $w, $x, $y] = $matches; if ($w != "\4") { - throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Hex::encode($val)); + throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Strings::bin2hex($val)); } $point = [ $curve->convertInteger(new BigInteger($x, 256)), diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php index cf11003b..fc12dd30 100644 --- a/phpseclib/File/X509.php +++ b/phpseclib/File/X509.php @@ -26,7 +26,6 @@ declare(strict_types=1); namespace phpseclib3\File; -use ParagonIE\ConstantTime\Hex; use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\Common\PrivateKey; use phpseclib3\Crypt\Common\PublicKey; @@ -1772,7 +1771,7 @@ class X509 $hash = new Hash('sha1'); $hash = $hash->hash($dn); extract(unpack('Vhash', $hash)); - return strtolower(Hex::encode(pack('N', $hash))); + return strtolower(Strings::bin2hex(pack('N', $hash))); } // Default is to return a string. diff --git a/phpseclib/Math/BigInteger/Engines/BCMath.php b/phpseclib/Math/BigInteger/Engines/BCMath.php index def5a8f4..3b6616b9 100644 --- a/phpseclib/Math/BigInteger/Engines/BCMath.php +++ b/phpseclib/Math/BigInteger/Engines/BCMath.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpseclib3\Math\BigInteger\Engines; -use ParagonIE\ConstantTime\Hex; +use phpseclib3\Common\Functions\Strings; use phpseclib3\Exception\BadConfigurationException; /** @@ -100,7 +100,7 @@ class BCMath extends Engine break; case 16: $x = (strlen($this->value) & 1) ? '0' . $this->value : $this->value; - $temp = new self(Hex::decode($x), 256); + $temp = new self(Strings::hex2bin($x), 256); $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; $this->is_negative = false; break; diff --git a/phpseclib/Math/BigInteger/Engines/Engine.php b/phpseclib/Math/BigInteger/Engines/Engine.php index 7b8bf6f6..dcbffc63 100644 --- a/phpseclib/Math/BigInteger/Engines/Engine.php +++ b/phpseclib/Math/BigInteger/Engines/Engine.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace phpseclib3\Math\BigInteger\Engines; -use ParagonIE\ConstantTime\Hex; use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\Random; use phpseclib3\Exception\BadConfigurationException; @@ -173,7 +172,7 @@ abstract class Engine implements \JsonSerializable $is_negative = false; if ($base < 0 && hexdec($x[0]) >= 8) { $this->is_negative = $is_negative = true; - $x = Hex::encode(~Hex::decode($x)); + $x = Strings::bin2hex(~Strings::hex2bin($x)); } $this->value = $x; @@ -267,7 +266,7 @@ abstract class Engine implements \JsonSerializable */ public function toHex(bool $twos_compliment = false): string { - return Hex::encode($this->toBytes($twos_compliment)); + return Strings::bin2hex($this->toBytes($twos_compliment)); } /** diff --git a/phpseclib/Math/BigInteger/Engines/PHP.php b/phpseclib/Math/BigInteger/Engines/PHP.php index 6fcf472e..77a19281 100644 --- a/phpseclib/Math/BigInteger/Engines/PHP.php +++ b/phpseclib/Math/BigInteger/Engines/PHP.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpseclib3\Math\BigInteger\Engines; -use ParagonIE\ConstantTime\Hex; +use phpseclib3\Common\Functions\Strings; use phpseclib3\Exception\BadConfigurationException; /** @@ -94,7 +94,7 @@ abstract class PHP extends Engine switch (abs($base)) { case 16: $x = (strlen($this->value) & 1) ? '0' . $this->value : $this->value; - $temp = new static(Hex::decode($x), 256); + $temp = new static(Strings::hex2bin($x), 256); $this->value = $temp->value; break; case 10: diff --git a/phpseclib/Math/BinaryField/Integer.php b/phpseclib/Math/BinaryField/Integer.php index b6bb12c8..5b69bbe0 100644 --- a/phpseclib/Math/BinaryField/Integer.php +++ b/phpseclib/Math/BinaryField/Integer.php @@ -22,7 +22,7 @@ declare(strict_types=1); namespace phpseclib3\Math\BinaryField; -use ParagonIE\ConstantTime\Hex; +use phpseclib3\Common\Functions\Strings; use phpseclib3\Math\BigInteger; use phpseclib3\Math\BinaryField; use phpseclib3\Math\Common\FiniteField\Integer as Base; @@ -448,7 +448,7 @@ class Integer extends Base */ public function toHex(): string { - return Hex::encode($this->toBytes()); + return Strings::bin2hex($this->toBytes()); } /** diff --git a/phpseclib/Math/PrimeField/Integer.php b/phpseclib/Math/PrimeField/Integer.php index 3927dffd..c1fd0a81 100644 --- a/phpseclib/Math/PrimeField/Integer.php +++ b/phpseclib/Math/PrimeField/Integer.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpseclib3\Math\PrimeField; -use ParagonIE\ConstantTime\Hex; +use phpseclib3\Common\Functions\Strings; use phpseclib3\Math\BigInteger; use phpseclib3\Math\Common\FiniteField\Integer as Base; @@ -302,7 +302,7 @@ class Integer extends Base */ public function toHex(): string { - return Hex::encode($this->toBytes()); + return Strings::bin2hex($this->toBytes()); } /**