Making Filters Work In Cgridview With Encrypted Fields

I have spent countless hours trying to figure this out, but I can’t get it to work!

How do I make the filters of a CGridView work with a field that is encrypted in the database? Basically what I need to do is to manipulate the value the user enters in the textfield for searching before it is compared with the value in the database.

I thought all I had to do was something like:




public function search()

...

$criteria->compare('email',manipulate($this->email),true);

...

}



where manipulate() is a function that manipulates the value the user enters to search for (in this case encrypts it,) BUT if I do that then, the cgridview does not diaplay any results at all (even when the user is not searching for a field).

After reading the documentation, it seems like the fields are populated by the findAll() function which I could override.




public function findAll($condition='',$params=array())

        {

            // change the $params here to manipulate the search fields (encrypt them). but HOW!?

            return parent::findAll($condition,$params);

        }



Any ideas?

I guess you are getting an un-existing value from manipulate() when an empty value is given.

Try the following:




if ($this->email != '')

{

    $criteria->compare('email',manipulate($this->email),true);

}



Other than that, I think it’s useless to use ‘LIKE’ comparison in the case of encrypted string.

manipulate("ABC") will not create a substring of manipulate("ABCDEFG"), right?

So you have to use the strict comparison to get a hit … Usually there should be no multiple results … Just one by one … It’s not a very easy and friendly operation for your user.

writing:




 if ($this->email != '')

     $criteria->compare('email',manipulate($this->email),true);



Solved the issue!

And you are totally right (I don’t know how I did not think of that before), what I am trying to do will not work unless I do a strict comparison because if the user email is: myemail@example.com, and I make a search for “myemail” the encryption of “myemail” will not be a substring of the encryption of myemail@example.com.

Now I have a big problem there!

Do you think its impossible to handle encrypted data for partial searching?

A little bit out of topic but related to this, I will also have a problem with the sorting of the encrypted fields!

If you can decrypt the encrypted values, it should be fairly easy possible anyway.

But, if you are not encrypting but hashing, as we usually do it for this kind of things, then it’s … um impossible. Partial matching and sorting altogether :(

It is a two way encryption. The password field is the only one using a hashing algorithm (but that one I do not need to search nor order by). The reason for encoding the email field is to protect the user privacy (if a hacker breaks into the database then he wont have the emails of the users).

So basically yes, it can be decrypted but I don’t know how could I make it work. Probably the encryption/decryption needs to be handles by the database instead of php so that I could search or order the encrypted fields. If not, I would have to decrypt all values of the table first, then search those values… I think it would be a very processor/memory intensive task :s

Yes, that’s the exact reason why I changed “fairly easy” to “possible anyway”.

Probably I would use CActiveRecord::findAll() + CArrayDataProvider instead of CActiveDataProvider.

Performance could be a possible problem, but I would start from there. :)