From a43ad7bdf5026b5d75a8b006eddf9b20ef10f405 Mon Sep 17 00:00:00 2001
From: Gary Allan <github@gallan.co.uk>
Date: Thu, 25 Jul 2019 12:35:31 +0100
Subject: [PATCH] Feature: Hook up PR #2667

---
 api/index.php                      | 11 ++---
 config.dist.php                    |  7 +++-
 functions/classes/class.Crypto.php | 67 +++++++++++++++++++++++-------
 3 files changed, 59 insertions(+), 26 deletions(-)

diff --git a/api/index.php b/api/index.php
index 23e54bbb..d9540508 100755
--- a/api/index.php
+++ b/api/index.php
@@ -66,16 +66,11 @@ try {
 
 	// crypt check
 	if($app->app_security=="crypt") {
-		$api_crypt_encryption_library = Config::get('api_crypt_encryption_library') === "mcrypt" ? 'mcrypt' : 'openssl';
-
-		// verify php extensions
-		if (!in_array($api_crypt_encryption_library, get_loaded_extensions())) {
-			$Response->throw_exception(500, 'php extension '.$api_crypt_encryption_library.' missing');
-		}
+		$encryption_method = Config::get('api_crypt_encryption_library', 'openssl-128-cbc');
 
 		// decrypt request - form_encoded
 		if(strpos($_SERVER['CONTENT_TYPE'], "application/x-www-form-urlencoded")!==false) {
-			$decoded = $User->Crypto->decrypt($_GET['enc_request'], $app->app_code, $api_crypt_encryption_library);
+			$decoded = $User->Crypto->decrypt($_GET['enc_request'], $app->app_code, $encryption_method);
 			if ($decoded === false) $Response->throw_exception(503, 'Invalid enc_request');
 			$decoded = $decoded[0]=="?" ? substr($decoded, 1) : $decoded;
 			parse_str($decoded, $encrypted_params);
@@ -84,7 +79,7 @@ try {
 		}
 		// json_encoded
 		else {
-			$encrypted_params = $User->Crypto->decrypt($_GET['enc_request'], $app->app_code, $api_crypt_encryption_library);
+			$encrypted_params = $User->Crypto->decrypt($_GET['enc_request'], $app->app_code, $encryption_method);
 			if ($encrypted_params === false) $Response->throw_exception(503, 'Invalid enc_request');
 			$encrypted_params = json_decode($encrypted_params, true);
 			$encrypted_params['app_id'] = $_GET['app_id'];
diff --git a/config.dist.php b/config.dist.php
index b77ed6ff..9073d1b7 100755
--- a/config.dist.php
+++ b/config.dist.php
@@ -75,9 +75,12 @@ $config['resolve_verbose']             = true;       // verbose response - print
 $debugging = false;
 
 /*
- * API Crypt security provider. "mcrypt" or "openssl"
+ * API Crypt security provider. "mcrypt" or "openssl*"
+ * Supported methods:
+ *    openssl-128-cbc (alias openssl, openssl-128) *default
+ *    openssl-256-cbc (alias openssl-256)
  *
- * default as of 1.3.2 "openssl"
+ * default as of 1.3.2 "openssl-128-cbc"
  ******************************/
 // $api_crypt_encryption_library = "mcrypt";
 
diff --git a/functions/classes/class.Crypto.php b/functions/classes/class.Crypto.php
index df472524..9f429db8 100644
--- a/functions/classes/class.Crypto.php
+++ b/functions/classes/class.Crypto.php
@@ -71,28 +71,65 @@ class Crypto {
      * encrypt data and base64 encode results
      * @param  string $rawdata
      * @param  string $password
-     * @param  string $encryption_library   (default value: "openssl")
+     * @param  string method   (default value: "openssl-128-cbc")
      * @return string|false
      */
-    public function encrypt($rawdata, $password, $encryption_library="openssl") {
-        if ($encryption_library === "mcrypt")
+    public function encrypt($rawdata, $password, $method="openssl-128-cbc") {
+        $method = $this->supported_methods($method);
+
+        if ($method === 'mcrypt')
             return $this->encrypt_using_legacy_mcrypt($rawdata, $password);
         else
-            return $this->encrypt_using_openssl($rawdata, $password, $encryption_library);
+            return $this->encrypt_using_openssl($rawdata, $password, $method);
     }
 
     /**
      * decrypt base64 encoded data
      * @param  string $base64data
      * @param  string $password
-     * @param  string $encryption_library   (default value: "openssl")
+     * @param  string $method   (default value: "openssl-128-cbc")
      * @return string|false
      */
-    public function decrypt($base64data, $password, $encryption_library="openssl") {
-        if ($encryption_library === "mcrypt")
+    public function decrypt($base64data, $password, $method="openssl-128-cbc") {
+        $method = $this->supported_methods($method);
+
+        if ($method === "mcrypt")
             return $this->decrypt_using_legacy_mcrypt($base64data, $password);
         else
-            return $this->decrypt_using_openssl($base64data, $password, $encryption_library);
+            return $this->decrypt_using_openssl($base64data, $password, $method);
+    }
+
+    /**
+     * Return a supported encryption method
+     * @param  string $method
+     * @return string
+     */
+    private function supported_methods($method) {
+        switch ($method) {
+            case 'mcrypt':
+                $retval = 'mcrypt';
+                break;
+
+            case 'openssl':
+            case 'openssl-128':
+            case 'openssl-128-cbc':
+                $retval = 'AES-128-CBC';
+                break;
+
+            case 'openssl-256':
+            case 'openssl-256-cbc':
+                $retval = 'AES-256-CBC';
+                break;
+
+            default:
+                $this->Result->show("danger", _("Error: "). _('Unsupported $api_crypt_encryption_library method: ').escape_input($method), true);
+        }
+
+        $required_ext = ($retval === 'mcrypt') ? 'mcrypt' : 'openssl';
+        if (!in_array($required_ext, get_loaded_extensions()))
+            $this->Result->show("danger", _("Error: "). _('php extension not installed: ').$required_ext, true);
+
+        return $retval;
     }
 
     // OpenSSL
@@ -101,12 +138,11 @@ class Crypto {
      * encrypt data and base64 encode results
      * @param  string $rawdata
      * @param  string $password
+     * @param  string $method
      * @return string|false
      */
-    private function encrypt_using_openssl($rawdata, $password, $key_size) {
-        $method = ($key_size == "openssl-256") ? 'AES-256-CBC' : 'AES-128-CBC';
-        
-        // Binary key derived from password
+    private function encrypt_using_openssl($rawdata, $password, $method) {
+        // Binary key derived from password (32 bytes)
         $key = openssl_digest($password, 'sha256', true);
         // Encrypt using IV
         $ivlen = openssl_cipher_iv_length($method);
@@ -124,12 +160,11 @@ class Crypto {
      * decrypt base64 encoded data
      * @param  string $base64data
      * @param  string $password
+     * @param  string $method
      * @return string|false
      */
-    private function decrypt_using_openssl($base64data, $password, $key_size) {
-        $method = ($key_size == "openssl-256") ? 'AES-256-CBC' : 'AES-128-CBC';
-
-        // Binary key derived from password
+    private function decrypt_using_openssl($base64data, $password, $method) {
+        // Binary key derived from password (32 bytes)
         $key = openssl_digest($password, 'sha256', true);
 
         $c = base64_decode($base64data);
-- 
GitLab