0

I found this question, which is identical to what I need to do: How do you Encrypt and Decrypt a PHP String? I've got everything working to the point of encrypting the data before it is saved. In the event function onExtensionBeforeSave, I have access to the table. I can get the values that need to be encrypted from jinput and encrypt them. What I can't figure out is how to put the encrypted data into the table object in a way that it will replace the un-encrypted data before it is stored/saved.

Rob
  • 357
  • 1
  • 3
  • 13

1 Answers1

0

I was able to figure this out. In the extension event onExtensionBeforeSave, I get the post data, load the config.xml file to check the form fields for my custom fields (type='encryptedtext'), encryt those and use the table object to bind and check it, so it will be stored correctly.

     function onExtensionBeforeSave($context, $table, $isNew)
 {
     $jinput = JFactory::getApplication()->input;
     $component = $jinput->get('component');

     if($component !== 'com_store') // Only encrypting fields in the store component for now
     {
         return true;
     }

     $form_path = JPATH_ADMINISTRATOR . '\\components\\' . $component . '\\config.xml';
     $xml = simplexml_load_file($form_path);
     $has_encrypted = false;
     foreach($xml->fieldset as $fieldset)
     {
         foreach($fieldset as $field)
         {
            if($field['type'] == 'encryptedtext') // is our custom form field type to be encrypted
            {
                $has_encrypted = true;
                if(!$fields) // get fields if it hasn't already been done
                {
                    $fields = $jinput->get('jform', '', 'array');   
                }
                $field = (string)$field['name'];
                $value = (string)$fields[$field];
                $cipher = "aes-256-ctr";
                $ivlen = openssl_cipher_iv_length($cipher);
                $iv = openssl_random_pseudo_bytes($ivlen, $isStrongCrypto);
                if (!$isStrongCrypto) 
                {
                    throw new \Exception("Not a strong key");
                }
                $keyhash = openssl_digest($component, 'sha256', true);
                $opts =  OPENSSL_RAW_DATA;
                $encrypted = openssl_encrypt($value, $cipher, $keyhash, $opts, $iv);
                if ($encrypted === false)
                {
                    throw new \Exception('Encryption failed: ' . openssl_error_string());
                }
                $result = $iv . $encrypted;
                $result = base64_encode($result);
                $fields[$field] = $result;
            }
         }
     }         
     if(!has_encrypted)
     {
         return false;
     }
     $data = array(
         'params'=>$fields,
         'option'=>$component
     );
     if (!$table->bind($data))
     {
         throw new RuntimeException($table->getError());
     }
     if (!$table->check())
     {
         throw new RuntimeException($table->getError());
     }
     return true;
}

All that is left is to decrypt it in the getInput function of the custom field. I answer this in case someone needs it, and I would love some critique if people see improvements, or if it's complete junk ...

Rob
  • 357
  • 1
  • 3
  • 13