Crypter Component

by Thades
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;
    }
}
?>

Report

More on Components

Advertising

Comments

  • abdul posted on 11/02/10 05:40:21 AM
    Hi,
    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.
  • bsonnich posted on 02/19/08 10:14:20 PM
    How do you accomplish both validation and encryption? I tried using the encryption beforeSave in the model, but that, of course, doesn't work. I am currently saving the encrypted credit card separately upon successfully validating and saving all fields. But, I'm thinking that there must be a better way than that.

    Thanks!
    • Thades posted on 02/20/08 12:08:56 AM
      How do you accomplish both validation and encryption? I tried using the encryption beforeSave in the model, but that, of course, doesn't work. I am currently saving the encrypted credit card separately upon successfully validating and saving all fields. But, I'm thinking that there must be a better way than that.

      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?
      • bsonnich posted on 02/20/08 11:09:12 AM
        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!
        • Thades posted on 02/21/08 07:55:34 PM
          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 ;)
  • bradbeattie posted on 01/17/08 12:18:19 PM
    Might I suggest the following?

    return str_pad(
    substr($cardNumber, -4),
    strlen($cardNumber)-4,
    'X',
    STR_PAD_LEFT
    );

    Haven't tested it, but the idea should do just fine.
  • fumble posted on 01/15/08 04:46:46 PM
    Thanks for posting this component.

    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.
    • Thades posted on 01/15/08 04:59:17 PM
      @Joel
      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 =)

      Thanks for posting this component.

      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.
      • utoxin posted on 01/16/08 09:26:08 PM
        @Joel
        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?

        In theory, they can be up to 19 characters under the current standard, but I don't know of anyone currently using over 16.
login to post a comment.