How And Where To Initialize Object To Handle Encryption (Phpseclib)?

I am new to Yii, and to PHP frameworks in general. I need a little help figuring this out:

The application I am developing needs to store user names and emails with encryption in the database. I think I will use the phpsec library. Here is what I have done so far:

  1. installed phpsec in vendors folder

  2. in congig/main.php I wrote:




'import'=>array(

                ...

                'application.vendors.phpseclib.Crypt.AES'

	),



What I need to do now is to initialize a cipher object like this:




$cipher = new Crypt_AES(CRYPT_AES_MODE_ECB);

$cipher->setPassword('whatever');



To finally be able to encrypt and decrypt:




$cipher->encrypt($plaintext)



What I do not know, is where to initialize the $cipher object. One idea I had is to do it in the User model, because the things that are going to be encrypted are the user’s data. In this case how would I do it? One possible way is to have an encrypt() and decrypt() function inside the User model and inside those functions initialize and do the encryption/decryption. But I do not know if it is a good idea to initialize the object each time the function is called.

Another thing that came to my mind is to have it as a component of my application. I read in another post that I could register a model in config/main.php, in the components array. something like:




'components'=>array(

    ...

   'Crypt_AES'=>array(

                        'class'=>'cipher',

   )

)



but to initialize the object I need to pass a parameter Crypt_AES(CRYPT_AES_MODE_ECB), so I am not sure how would that work. Also I believe I need to copy the php file to modules instead of the vendors folder?

I am a little bit lost.

I guess the most appropriate course of action is to perform the encryption in the user model’s beforeSave() method and the decryption in the model’s afterFind() method. You should probably create additional attributes in the model (but not in the database) to hold the plain text version of each field.

In beforeSave(), encrypt the plain text field and store the result in the relevant encrypted field.

In afterFind(), decrypt the encrypted field and store the result in the relevant plain text field.

Make sure you call the parent implementations in both methods.

What I did (for now) but I think is not the perfect solution is to add this two methods in the User model:




public function encrypt($text){

            $cipher = new Crypt_AES();

            $cipher->setPassword(Yii::app()->params['cipherPass']);

            return bin2hex($cipher->encrypt($text));

        }

 public function decrypt($text){

            $cipher = new Crypt_AES();

            $cipher->setPassword(Yii::app()->params['cipherPass']);

            return $cipher->decrypt(pack("H*" , $text));

        }



Then, as you said I did the following in the beforeSave() method:




public function beforeSave()

        {


          if (!empty($this->first_name)) 

              $this->first_name = $this->encrypt($this->first_name);

          

           ...

        }



The problems I see:

Every time the encrypt/decrypt functions are called, the $cipher object is initializing. I think this is not optimal (but I am not sure). Is there a way to initialize the object in something like the constructor of the User class and store it in a class property to then call $this->cipher->encrypt()?

Yes, I’m sure you could do exactly that. Just create a new instance variable and initialise it in the constructor.

Again, make sure you’re calling the parent class versions of beforeSave() and afterSave() appropriately in the methods or the events won’t be raised properly.

They should look something like this:




	protected function beforeSave()

	{

		// Do stuff here


		return parent::beforeSave();

	}


	protected function afterFind()

	{

		// Do other stuff here


		parent::afterFind();

	}



I am sorry for the next question but I am very new at OOP, I dont see a constructor for the User class. searching in google I see that php 5 constructors are called "__construct", so do I just put a function called "__construct" ? and there initialize the object? I dont know if that is going to mess up yii.

Right now, the way I have it (with the beforeSave and afterFind methods initializing the object) everything works perfectly, BUT I noticed a problem: because data is encrypted, when I go to manage users section, the search fields do not work. Probably the unencryption needs to be made in beforeFind() instead of afterFind()? I tried that but it does not work. I think it is because I don’t know how to use the beforeFind function, but I think I am getting close…