Crypter Component
I never could get MySQL's encryption routines to work properly for me so, I created this component to help me out. This is based on the fact that I needed encryption as well as decryption. If you have the same problems and need this type of functionality, feel free to use this.
This code is the example on http://us.php.net/manual/en/ref.mcrypt.php rolled into a component. This works wonderfully.
Please note that this code has not been tested using cake's testing facility and the code is provided AS IS.
The mcrypt module must be enabled in the php.ini!
Please visit http://us.php.net/manual/en/ref.mcrypt.php for more information
<?php
class CrypterComponent extends Object {
/**
* ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING !
*
* Do not change this key after we are in production unless you know what
* the hell you are doing!! If you change this key, no one can process
* payments!
*
* If you want to change your key every so often, decrypt all the data that
* has been previously encrypted and store as plain text somewhere, change
* the key and then re-encrypt it.
*
* ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING ! WARNING !
*/
var $key = 'PuTyOuRK3yHeRe'; <----change this.
var $name = "Crypter";
/**
* This function will encrypt the string that is passed to it
*
* @param String $data The string to be encrypted.
* @return String Returns the encrypted string or false
* @access public
*/
function enCrypt($data = null) {
if ($data != null) {
// Make an encryption resource using a cipher
$td = mcrypt_module_open('cast-256', '', 'ecb', '');
// Create and encryption vector based on the $td size and random
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
// Initialize the module using the resource, my key and the string vector
mcrypt_generic_init($td, $this->key, $iv);
// Encrypt the data using the $td resource
$encrypted_data = mcrypt_generic($td, $data);
// Encode in base64 for DB storage
$encoded = base64_encode($encrypted_data);
// Make sure the encryption modules get un-loaded
if (!mcrypt_generic_deinit($td) || !mcrypt_module_close($td)) {
$encoded = false;
}
} else {
$encoded = false;
}
return $encoded;
}
/**
* This function will de-crypt the string that is passed to it
*
* @param String $data The string to be encrypted.
* @return String Returns the encrypted string or false
*/
function deCrypt($data = null) {
if ($data != null) {
// The reverse of encrypt. See that function for details
$data = (string) base64_decode(trim($data));
$td = mcrypt_module_open('cast-256', '', 'ecb', '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $this->key, $iv);
$data = (string) trim(mdecrypt_generic($td, $data));
// Make sure the encryption modules get un-loaded
if (!mcrypt_generic_deinit($td) || !mcrypt_module_close($td)) {
$data = false;
}
} else {
$data = false;
}
return $data;
}
/**
* This method will mask a credit card number
*
* @param String $cardNumber The card number to be masked
* @return String The masked card number
* @access public
*/
function maskCardNumber($cardNumber) {
$cardArray = str_split($cardNumber);
$length = count($cardArray);
$maskedCardNumber = "";
// Mask all numbers except the last 4
for ($i = 0; $i < $length -4; $i++) {
$cardArray[$i] = 'X';
}
// Turn back into a string
for ($i = 0; $i < $length; $i++) {
$maskedCardNumber = $maskedCardNumber . $cardArray[$i];
}
return $maskedCardNumber;
}
}
?>

Please suggest how can i restrict to the '/' character in encrypted string as because problems occur when this data passes through url. I am really facing this problem. Suppose if i encrypt the data 12830 I have ''POvfhA49DY9U6q5g/7zgrQ==" as coded here I dont want the '/' inside the code because its divides into parameter.
Please suggest me.
Thanks!
From my point of view, and I still believe this is CakePHP's point of view, is that the component is to the controller what the helper is to the view.
So, if I am understanding the question correctly, you want the credit card encrypted using beforeSave. Based on that just copy the encryption and paste it into your model. In the before save, call the function. This way, it passed validation and then it will encrypt before the save.
You cannot call a component method in the model unless you specifically instantiate the object within the model.
Is this the answer to your question?
Yes. That's it. I have to set the key in both the model and the component now. Is there a way that would be more ideal?
Thank you very much!
Well, once the component is loaded, the sky is the limit! The only thing you have to remember is that the model is not designed to access the component and vice-versa.
Off the top of my head there are tons of ways to get around this but, for the sake of keeping to convention, you should store it in both places.
There is nothing saying that you cannot make a "Crypter Model" and just load that in the controller when you want the encryption functions but, model to model won't work again.
One of them is going to have to do it and the only two things that interact are the controller and model.
Don't know what else to tell you except that if you really wanted to, load the component in the model but, don't expect support from the cake community if you do that ;)
return str_pad(
substr($cardNumber, -4),
strlen($cardNumber)-4,
'X',
STR_PAD_LEFT
);
Haven't tested it, but the idea should do just fine.
Question: I'm not understanding the reasoning for the loops in maskCardNumber()? Why not just:
function maskCardNumber($cardNumber) {
return 'XXXXXXXXXXXX' . substr( $cardNumber, -4 );
}
Thanks again.
To be honest, I am not sure if there are any credit card numbers out there longer than 16 characters. I guess this would be a good implementation until (if there aren't already) cards longer than 16. Do you know of any?
With this loop, you can have a card number longer than 16. I really don't know how the rest of the credit cards throughout the world look =)
In theory, they can be up to 19 characters under the current standard, but I don't know of anyone currently using over 16.