How to encrypt data

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • CharliSTV
    Junior Member
    • Nov 2019
    • 1

    How to encrypt data

    Hi.
    I am trying to encrypt some data that I need to store in the database, but I don't know exactly which classes are responsible for the process of storing for example the field description for contact entity.

    Could you help me please?​​​​​​

    ​Thanks
  • tothewine
    Active Community Member
    • Jan 2018
    • 373

    #2
    to save look for hooks in github documentation
    to read override get method in service class for your record

    Comment

    • telecastg
      Active Community Member
      • Jun 2018
      • 907

      #3
      I would suggest to create an beforeSave hook for Contact entity like this:

      custom/EspoCustom/Hooks/Contact/ContactHooks.php
      Code:
      <?php
      
      namespace Espo\Custom\Hooks\Contact;
      
      use Espo\ORM\Entity;
      
      class ContactHooks extends \Espo\Core\Hooks\Base
      {
      
          public function beforeSave(Entity $entity, array $options=array())
          {    
              // get the un​​​​​​-encrypted description from the model
              $description = $entity->get('description');
      
              // encrypt the description field prior to storing in database
      $fileM = new \Espo\Core\Utils\File\Manager();
      $config = new \Espo\Core\Utils\Config($fileM);
              $descriptionHash = new \Espo\Core\Utils\PasswordHash($config);
              $encodedDescription = $descriptionHash->hash($description,true);
      
              // store the encoded description in the model
              $entity->set('description', $encodedDescription);
          }
      
      }
      Please note that this is similar to the code that I use to encode passwords for new users but haven't tested it actually encrypting the description field, so this code is good for writing encrypted data but you will need to follow tothewine suggestion and overwrite the get method in the service class for Contact to be able to read the field, but since I haven't done that myself, I can't provide any guidance about it.

      Please correspond to our efforts to help by posting your solution after you implement it, so other participants can benefit also.

      Cheers
      Last edited by telecastg; 01-11-2020, 05:11 AM.

      Comment

      • item
        Active Community Member
        • Mar 2017
        • 1476

        #4
        Hello,
        nice thanks

        the best is in entityManager -> fieldAttribute -> checkbox : isEncrypted ..
        so it's outOfBox and we can decide witch is encrypted or not.

        i think it's not difficult to implement this

        Regards

        If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

        Comment

        • telecastg
          Active Community Member
          • Jun 2018
          • 907

          #5
          Thanks item, it sounds a lot easier that having to code hooks !

          Do you know if this setting also takes care of the mechanism for entering the password and reading the encrypted file ?

          Comment

          • item
            Active Community Member
            • Mar 2017
            • 1476

            #6
            Hello telecastg,
            sorry i have not skill for this kind of .. and not understand :s ... but for me it's easy for someone have skill :

            1) common hook (orm entity maybe)
            2) check if field have attribute isEncrypted (like personalData or required or.... )
            3) then crypt data ..

            i have make search for "personalData" in openFiles in sublimeText.
            fieldManager and/or entity are i think where the solution can be ok.

            Regards

            If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

            Comment

            • Kyle
              Senior Member
              • May 2020
              • 143

              #7
              Hi,
              I have been unable to find this option entityManager -> fieldAttribute -> checkbox : isEncrypted
              Is it only available for some field types? Does anyone have a entity definition for a field using encryption they can share?

              Comment

              • item
                Active Community Member
                • Mar 2017
                • 1476

                #8
                Hello Kyle,
                i just say : a feature request .. isEncrypted is not out-of-box and not avaible.. maybe some one can develop this.
                If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

                Comment

                • Kyle
                  Senior Member
                  • May 2020
                  • 143

                  #9
                  Hi item,
                  Thanks for clarifying that for me.

                  Comment

                  • Ananya K
                    Member
                    • Jul 2020
                    • 50

                    #10
                    Hey Kyle
                    Even I was trying to encrypt some of the personal data of the client in our database. And I am able to do that also.

                    I did Application level encryption for the data before saving it into the Database.

                    - I came up with a Encryption class which will take data(string) and the secret key as parameters to the class constructor.
                    - espocrm/custom/Espo/Custom/Core/Utils/Encryption.php
                    - Under the entity which will store the field that needs to be encrypted i wrote afterUpdate() function to call the encryption process.
                    - The encryption function will take the fetched value of the field and encrypt using the secret key provided with the IV value.
                    - Store both the IV value and the cipher text in the Database.
                    - While reading the value in the UI (with specific role and access) make a get request for that field.
                    - Decrypt the cipher text using the same IV and secret key then return the value back to the UI.

                    I have used following php encryption and decryption functions.
                    - AES-256-CBC => method
                    - openssl_cipher_iv_length => For IV length
                    - openssl_random_pseudo_bytes => For generating the IV
                    - openssl_encrypt => to encrypt
                    - openssl_decrypt => to decrypt

                    I am able to store the data in DB in encrypted format and also able to decrypt and read the data.
                    Last edited by Ananya K; 11-23-2020, 01:06 PM.

                    Comment


                    • blackmirror
                      blackmirror commented
                      Editing a comment
                      Hello Ananya,
                      can you please give us more information about this solution? Which files did you edit on the front-end?
                      I think it will be useful for a lot of people.
                      If you can, put your encryption and decrypt code.
                  • telecastg
                    Active Community Member
                    • Jun 2018
                    • 907

                    #11
                    Very nice !, thanks so much for sharing Ananya K

                    Comment

                  • Ananya K
                    Member
                    • Jul 2020
                    • 50

                    #12
                    Hi,

                    I would like to add a detailed solution for the Encryption of the field in Espocrm.
                    • Step1:
                      • I created a custom Class for the encryption process.
                        • espocrm/custom/Espo/Custom/Core/Utils/Encryption.php
                          • This class you can use to create your own encrypt and decrypt functions.
                    PHP Code:
                    <?php
                    
                    namespace Espo\Custom\Core\Utils;
                    
                    class Encryption
                    {
                        private $secret_key = null;
                        private $iv = null;
                        protected $method = 'AES-256-CBC';
                    
                    public function __construct($secret_key, $iv = null, $method = 'AES-256-CBC')
                    {
                        $this-&gt;secret_key = $secret_key;
                        if ($iv) {
                        $this-&gt;iv = hex2bin($iv);
                    }
                    }
                    
                    public static function get_random_key($length)
                    {
                        return openssl_random_pseudo_bytes($length, $crypto_strong);
                    }
                    
                    public function get_algorithms()
                    {
                        return $this-&gt;method;
                    }
                    
                    public function set_algorithms($algorithm)
                    {
                        $methods = $this-&gt;available_algorithms();
                        if (isset($methods[$algorithm])) {
                        $this-&gt;method = $algorithm;
                    } else {
                        throw new \Exception('Encryption ['.$algorithm.'] method is not available', 1);
                    }
                    }
                    
                    public function available_algorithms()
                    {
                        return openssl_get_cipher_methods();
                    }
                    
                    public function encrypt($string_data)
                    {    // Use the openssl_encrypt to generate the ciphertext for the given $string_data and return the same.}
                    
                    public function get_ivlen()
                    {
                        return $this-&gt;ivlen;
                    }
                    
                    public function get_iv()
                    {
                        return bin2hex($this-&gt;iv);
                    }
                    
                    public function decrypt($string_cypher)
                    {
                        // Use the openssl_decrypt to generate the string text for the given $string_cypher and return the same.
                    }
                    }
                    • Step 2:
                      • In my case, I wanted to encrypt the personal data. A foreign field under the Contact table from the Personal Client Data table.
                      • Created a custom field view foreign-varchar for personal data string under the Contact.
                        • espocrm/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json
                    PHP Code:
                    "personalData": {
                        "readOnly": false,
                        "maxLength": 11,
                        "type": "foreign",
                        "link": "personalData",
                        "field": "personalDataString",
                        "view": "custom:views/fields/foreign-varchar",
                        "tooltip": true,
                        "isCustom": true,
                        "exportDisabled": true,
                        "isEncrypted ": true,
                        "isPersonalData": true
                    }, 
                    
                    • espocrm/client/custom/src/views/fields/foreign-varchar.js
                    Code:
                    Espo.define('custom:views/fields/foreign-varchar', 'views/fields/foreign-varchar', function (Dep) {
                    return Dep.extend({
                        type: 'foreign',
                        initInlineEdit: function () {
                            this.$el.addClass('hidden');
                            var $cell = this.getCellElement();
                            var $editLink = $('&lt;a href="javascript:" class="pull-right inline-edit-link hidden"&gt;&lt;span class="fas fa-pencil-alt fa-sm"&gt;&lt;/span&gt;&lt;/a&gt;');
                            if ($cell.length == 0) {
                                this.listenToOnce(this, 'after:render', this.initInlineEdit, this);
                                return;
                            }
                            $cell.prepend($editLink);
                            $cell.on('mouseenter', function (e) {
                            if (this.disabled || this.readOnly) {
                               return;
                            }
                        }.bind(this)).on('mouseleave', function (e) {
                            e.stopPropagation();
                        }.bind(this));
                    
                    
                        $editLink.on('click', function () {
                            this.notify(this.translate('pleaseWait', 'messages'));
                            this.ajaxGetRequest('API path to get the descrypted string' + this.model.id).done(function (response) {
                            this.model.set('personalData', response.personalDataDecrypt);
                            this.notify(false);
                        }.bind(this));
                            this.inlineEdit();
                        }.bind(this));
                    },
                    inlineEditClose: function (dontReset) {
                        this.trigger('inline-edit-off');
                        this._isInlineEditMode = false;
                        if (this.mode != 'edit') {
                           return;
                        }
                       this.setMode('detail');
                       this.once('after:render', function () {
                           this.removeInlineEditLinks();
                       }, this);
                       if (!dontReset) {
                           this.model.set(this.initialAttributes);
                       }
                       this.reRender(true);
                       this.trigger('after:inline-edit-off');
                       this.initInlineEdit();
                    }
                    });
                    • Step 3:
                      • Storing the encrypted data to the database.
                        • Use the function afterUpdate().
                        • Define your own function like encryptPersonalData() based on your need. (ie. Including validation and all).
                    PHP Code:
                    protected function afterUpdateEntity(Entity $entity, $data)
                    {
                        if (($entity->isAttributeChanged('personalData'))) {
                            $this->getRecordService('Contact')->encryptPersonalData($entity->get('personalData'));
                        }
                    } 
                    
                    • Step 4:
                      • Reading the data in the UI.
                        • In my use case, I will decrypt the data when the inline edit is pressed. So we will decrypt the data and show it in the edit text box.
                          • This is present in the espocrm/client/custom/src/views/fields/foreign-varchar.js file where the ajax call is made to get the data.
                        • The Controller to get decrypt data.
                    PHP Code:
                    public function getActionGetSSNSuffix($params, $data, $request)
                    {
                        return $this->getRecordService()->decryptPersonalData();
                    } 
                    
                    • And create your own service function to decrypt the data.

                    Comment

                    • khopper
                      Senior Member
                      • Sep 2017
                      • 329

                      #13
                      yuri I double down on this enhancement request! Think about it, encypted fields would mean your product would have better security and help bring it in the medical field where HIPPA requirements are harsh!

                      item
                      request was:
                      the best is in entityManager -> fieldAttribute -> checkbox : isEncrypted ..
                      so it's outOfBox and we can decide witch is encrypted or not.​

                      Comment

                      Working...