From 414a9509aa09061631e3ae0b96a2432717a1c99b Mon Sep 17 00:00:00 2001 From: djmaze Date: Wed, 10 Nov 2021 10:36:16 +0100 Subject: [PATCH] Added support for sodium_crypto_aead_xchacha20poly1305_ietf encryption --- .../app/libraries/RainLoop/Actions/Admin.php | 2 +- .../libraries/RainLoop/Actions/UserAuth.php | 20 ++++-- .../0.0.0/app/libraries/snappymail/crypt.php | 64 +++++++++++++++---- snappymail/v/0.0.0/check.php | 1 + 4 files changed, 66 insertions(+), 21 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php index 9d8b14c01..62c82ddd0 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php @@ -696,7 +696,7 @@ trait Admin public function DoAdminPHPExtensions() : array { $aResult = []; - foreach (['APCu', 'cURL','GD','Gmagick','Imagick','intl','LDAP','pdo_mysql','pdo_pgsql','pdo_sqlite','XXTEA','Zip'] as $name) { + foreach (['APCu', 'cURL','GD','Gmagick','Imagick','intl','LDAP','OpenSSL','pdo_mysql','pdo_pgsql','pdo_sqlite','Sodium','XXTEA','Zip'] as $name) { $aResult[] = [ 'name' => $name, 'loaded' => \extension_loaded(\strtolower($name)) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php index 6c6df0b2b..7c1c571c8 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php @@ -235,9 +235,15 @@ trait UserAuth $uuid = \SnappyMail\UUID::generate(); \SnappyMail\Crypt::setCipher($this->Config()->Get('security', 'encrypt_cipher', '')); - $data = \SnappyMail\Crypt::EncryptRaw($oAccount); + $data = \SnappyMail\Crypt::Encrypt($oAccount); if ('xxtea' === $data[0]) { + static::SetSignMeTokenCookie(array( + 'e' => $oAccount->Email(), + 'u' => $uuid, + 'x' => \base64_encode($data[1]) + )); + } else if ('sodium' === $data[0]) { static::SetSignMeTokenCookie(array( 'e' => $oAccount->Email(), 'u' => $uuid, @@ -247,7 +253,7 @@ trait UserAuth static::SetSignMeTokenCookie(array( 'e' => $oAccount->Email(), 'u' => $uuid, - 'i' => \base64_encode($data[1]) + 'o' => \base64_encode($data[1]) )); } @@ -274,10 +280,12 @@ trait UserAuth return null; } \SnappyMail\Crypt::setCipher($this->Config()->Get('security', 'encrypt_cipher', '')); - if (!empty($aTokenData['s'])) { - $aAccountHash = \SnappyMail\Crypt::XxteaDecrypt($sAuthToken, \base64_decode($aTokenData['s'])); - } else if (!empty($aTokenData['i'])) { - $aAccountHash = \SnappyMail\Crypt::OpenSSLDecrypt($sAuthToken, \base64_decode($aTokenData['i'])); + if (!empty($aTokenData['x'])) { + $aAccountHash = \SnappyMail\Crypt::XxteaDecrypt($sAuthToken, \base64_decode($aTokenData['x'])); + } else if (!empty($aTokenData['s'])) { + $aAccountHash = \SnappyMail\Crypt::SodiumDecrypt($sAuthToken, \base64_decode($aTokenData['s'])); + } else if (!empty($aTokenData['o'])) { + $aAccountHash = \SnappyMail\Crypt::OpenSSLDecrypt($sAuthToken, \base64_decode($aTokenData['o'])); } if (!empty($aAccountHash) && \is_array($aAccountHash)) { $oAccount = Account::NewInstanceFromTokenArray($this, $aAccountHash); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php b/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php index 6565fe74a..f9ff6a505 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/crypt.php @@ -68,31 +68,53 @@ abstract class Crypt ); } - public static function EncryptRaw($data) : array + public static function Encrypt($data) : array { + if (\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) { + $nonce = \random_bytes(24); + return ['sodium', $nonce, static::SodiumEncrypt($data, $nonce)]; + } + if (static::$cipher && \is_callable('openssl_encrypt')) { $iv = \random_bytes(\openssl_cipher_iv_length(static::$cipher)); - $data = \openssl_encrypt( - \json_encode($data), - static::$cipher, - static::Passphrase(), - OPENSSL_RAW_DATA, - $iv - ); - return [static::$cipher, $iv, $data]; + return ['openssl', $nonce, static::OpenSSLEncrypt($data, $iv)]; } $salt = \random_bytes(16); return ['xxtea', $salt, static::XxteaEncrypt($data, $salt)]; } - public static function OpenSSLDecrypt(string $data, string $iv) + public static function SodiumDecrypt(string $data, string $nonce) { - if (!$data || !$iv) { + if (!\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt')) { return null; } - if (!static::$cipher || !\is_callable('openssl_decrypt')) { - return static::XxteaDecrypt($data, $iv); + return \json_decode(\sodium_crypto_aead_xchacha20poly1305_ietf_decrypt( + $data, + APP_SALT, + $nonce, + static::Passphrase() + + )); + } + + public static function SodiumEncrypt($data, string $nonce) : ?string + { + if (!\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) { + return null; + } + return \sodium_crypto_aead_xchacha20poly1305_ietf_encrypt( + \json_encode($data), + APP_SALT, + $nonce, + \str_pad('', \SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES, static::Passphrase()) + ); + } + + public static function OpenSSLDecrypt(string $data, string $iv) + { + if (!$data || !$iv || !static::$cipher || !\is_callable('openssl_decrypt')) { + return null; } return \json_decode(\openssl_decrypt( $data, @@ -103,6 +125,20 @@ abstract class Crypt ), true); } + public static function OpenSSLEncrypt($data, string $iv) : ?string + { + if (!$data || !$iv || !static::$cipher || !\is_callable('openssl_encrypt')) { + return null; + } + return \openssl_encrypt( + \json_encode($data), + static::$cipher, + static::Passphrase(), + OPENSSL_RAW_DATA, + $iv + ); + } + public static function XxteaDecrypt(string $data, string $salt) { if (!$data || !$salt) { @@ -115,7 +151,7 @@ abstract class Crypt , true); } - public static function XxteaEncrypt($data, string $salt) : string + public static function XxteaEncrypt($data, string $salt) : ?string { if (!$data || !$salt) { return null; diff --git a/snappymail/v/0.0.0/check.php b/snappymail/v/0.0.0/check.php index 28d8d654b..cd5c19855 100644 --- a/snappymail/v/0.0.0/check.php +++ b/snappymail/v/0.0.0/check.php @@ -20,6 +20,7 @@ 'OpenSSL' => extension_loaded('openssl'), 'mysql' => extension_loaded('pdo_mysql'), 'pgsql' => extension_loaded('pdo_pgsql'), + 'Sodium' => extension_loaded('sodium'), 'sqlite' => extension_loaded('pdo_sqlite'), 'xxtea' => extension_loaded('xxtea'), 'zip' => extension_loaded('zip')