Validating encrypted/hashed unique attributes


In light of all the recent data breaches (think Sony) I need to encrypt (e.g. credit card number) and hash (e.g. email address) some table columns that must also be unique (none are primary keys, though). I’ve been reading a lot of the Yii documentation, wiki and forum posts and am still confused on the best way to insure uniqueness in the rules() function of the model.

I would like to use the ‘unique’ validator but the problem is that:

a. for an insert the form input must be encrypted/hashed

b. for an update the stored data must be decrypted or the form input must be hashed

before testing for uniqueness. Is there a simple way to achieve this?

If not, I should probably create my own validator class but don’t quite understand how retrieve the table row data before doing the comparison; somehow I think that ActiveRecord won’t help me so I’ll have to use DAO.

Any help will be greatly appreciated.

If I’ve understood correctly, then I would treat all data as encrypted. For example, hook into the beforeValidate() function as such. The only way I can think of doing this right now is to have a “temporary” version of each property which will store the hashed data, and the rules() should check against these temporary properites.

public function beforeValidate() {


  // For all hashed/encrypted properties

  $this->property1_temp = md5($this->property1);

  $this->property2_temp = md5($this->property2);

  // etc...



This way, the uniqueness test will be done on hashed values. I’m assuming you won’t be encrypting with salts, so two identical strings, once encrypted, will equal exactly the same hash.

You can then make sure the encrypted data is saved to the database in beforeSave(),

public function beforeSave() {

  $this->property1 = $this->property1_temp;



Thanks for your prompt reply. Yes, I though about using the before() methods but what I didn’t consider was treating all data as encrypted (because it’s not). I’ll try a couple of approaches with your suggestion to see how they work; thank you. I’ll also appreciate any other ideas.

When I said treating all data as encrypted, I didn’t mean all data! Just the properties that you need encrypted - the rest should stay as plain text.

Yes, I understand - I get the picture; the before() methods will execute regardless… Thanks again.