Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpmyadmin/phpmyadmin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurício Meneghini Fauth <mauricio@fauth.dev>2021-10-16 20:23:02 +0300
committerMaurício Meneghini Fauth <mauricio@fauth.dev>2022-01-10 18:19:42 +0300
commit3c11d62b31acdc994ae426999b5cf639cbdd32c9 (patch)
treea4364ee4db80ea7a5baaafc99fcc13b630f7ea22 /libraries
parent28ad63c96916ac1f81b7266faab65d3e7c9205ef (diff)
Add support for Sodium encryption
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
Diffstat (limited to 'libraries')
-rw-r--r--libraries/classes/Crypto/Crypto.php95
-rw-r--r--libraries/classes/Url.php8
-rw-r--r--libraries/config.default.php7
3 files changed, 96 insertions, 14 deletions
diff --git a/libraries/classes/Crypto/Crypto.php b/libraries/classes/Crypto/Crypto.php
index 128598639d..5f12fbdcae 100644
--- a/libraries/classes/Crypto/Crypto.php
+++ b/libraries/classes/Crypto/Crypto.php
@@ -7,14 +7,34 @@ use phpseclib\Crypt\Random;
final class Crypto
{
+ /** @var bool */
+ private $hasRandomBytesSupport;
+
+ /** @var bool */
+ private $hasSodiumSupport;
+
+ public function __construct()
+ {
+ $this->hasRandomBytesSupport = is_callable('random_bytes');
+ $this->hasSodiumSupport = $this->hasRandomBytesSupport
+ && is_callable('sodium_crypto_secretbox')
+ && is_callable('sodium_crypto_secretbox_open')
+ && defined('SODIUM_CRYPTO_SECRETBOX_NONCEBYTES')
+ && defined('SODIUM_CRYPTO_SECRETBOX_KEYBYTES');
+ }
+
/**
* @param string $plaintext
*
* @return string
*/
- public static function encrypt($plaintext)
+ public function encrypt($plaintext)
{
- return self::encryptWithPhpseclib($plaintext);
+ if ($this->hasSodiumSupport) {
+ return $this->encryptWithSodium($plaintext);
+ }
+
+ return $this->encryptWithPhpseclib($plaintext);
}
/**
@@ -22,9 +42,38 @@ final class Crypto
*
* @return string
*/
- public static function decrypt($ciphertext)
+ public function decrypt($ciphertext)
{
- return self::decryptWithPhpseclib($ciphertext);
+ if ($this->hasSodiumSupport) {
+ return $this->decryptWithSodium($ciphertext);
+ }
+
+ return $this->decryptWithPhpseclib($ciphertext);
+ }
+
+ /**
+ * @return string
+ */
+ private function getEncryptionKey()
+ {
+ global $PMA_Config;
+
+ $keyLength = $this->hasSodiumSupport ? SODIUM_CRYPTO_SECRETBOX_KEYBYTES : 32;
+
+ $key = $PMA_Config->get('URLQueryEncryptionSecretKey');
+ if (is_string($key) && mb_strlen($key, '8bit') === $keyLength) {
+ return $key;
+ }
+
+ $key = isset($_SESSION['URLQueryEncryptionSecretKey']) ? $_SESSION['URLQueryEncryptionSecretKey'] : null;
+ if (is_string($key) && mb_strlen($key, '8bit') === $keyLength) {
+ return $key;
+ }
+
+ $key = $this->hasRandomBytesSupport ? random_bytes($keyLength) : Random::string($keyLength);
+ $_SESSION['URLQueryEncryptionSecretKey'] = $key;
+
+ return $key;
}
/**
@@ -32,11 +81,11 @@ final class Crypto
*
* @return string
*/
- private static function encryptWithPhpseclib($plaintext)
+ private function encryptWithPhpseclib($plaintext)
{
- $key = self::getEncryptionKey();
+ $key = $this->getEncryptionKey();
$cipher = new AES(AES::MODE_CBC);
- $iv = Random::string(16);
+ $iv = $this->hasRandomBytesSupport ? random_bytes(16) : Random::string(16);
$cipher->setIV($iv);
$cipher->setKey($key);
$ciphertext = $cipher->encrypt($plaintext);
@@ -50,9 +99,9 @@ final class Crypto
*
* @return string|null
*/
- private static function decryptWithPhpseclib($encrypted)
+ private function decryptWithPhpseclib($encrypted)
{
- $key = self::getEncryptionKey();
+ $key = $this->getEncryptionKey();
$hmac = mb_substr($encrypted, 0, 32, '8bit');
$iv = mb_substr($encrypted, 32, 16, '8bit');
$ciphertext = mb_substr($encrypted, 48, null, '8bit');
@@ -69,12 +118,34 @@ final class Crypto
}
/**
+ * @param string $plaintext
+ *
* @return string
*/
- private static function getEncryptionKey()
+ private function encryptWithSodium($plaintext)
{
- global $PMA_Config;
+ $key = $this->getEncryptionKey();
+ $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
+ $ciphertext = sodium_crypto_secretbox($plaintext, $nonce, $key);
+
+ return $nonce . $ciphertext;
+ }
+
+ /**
+ * @param string $encrypted
+ *
+ * @return string|null
+ */
+ private function decryptWithSodium($encrypted)
+ {
+ $key = $this->getEncryptionKey();
+ $nonce = mb_substr($encrypted, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
+ $ciphertext = mb_substr($encrypted, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
+ $decrypted = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
+ if ($decrypted === false) {
+ return null;
+ }
- return $_SESSION[' HMAC_secret '] . $PMA_Config->get('blowfish_secret');
+ return $decrypted;
}
}
diff --git a/libraries/classes/Url.php b/libraries/classes/Url.php
index c5c411df0b..b5594b38ed 100644
--- a/libraries/classes/Url.php
+++ b/libraries/classes/Url.php
@@ -240,7 +240,9 @@ class Url
*/
public static function encryptQuery($query)
{
- return strtr(base64_encode(Crypto::encrypt($query)), '+/', '-_');
+ $crypto = new Crypto();
+
+ return strtr(base64_encode($crypto->encrypt($query)), '+/', '-_');
}
/**
@@ -249,7 +251,9 @@ class Url
*/
public static function decryptQuery($query)
{
- return Crypto::decrypt(base64_decode(strtr($query, '-_', '+/')));
+ $crypto = new Crypto();
+
+ return $crypto->decrypt(base64_decode(strtr($query, '-_', '+/')));
}
/**
diff --git a/libraries/config.default.php b/libraries/config.default.php
index fdd7c13639..b81981ba45 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -825,6 +825,13 @@ $cfg['IgnoreMultiSubmitErrors'] = false;
$cfg['URLQueryEncryption'] = true;
/**
+ * A secret key used to encrypt/decrypt the URL query string. Should be 32 bytes long.
+ *
+ * @global string $cfg['URLQueryEncryptionSecretKey']
+ */
+$cfg['URLQueryEncryptionSecretKey'] = '';
+
+/**
* allow login to any user entered server in cookie based authentication
*
* @global boolean $cfg['AllowArbitraryServer']