• Dec
  • 17
  • 2010

Using PHP to Encrypt Credit Card Data for Storage in a Database

by Andrew Kandels

One of the issues with working in the software-as-a-service industry is that credit card numbers often have to be stored locally in a database. Keeping it on file with your payment gateway alone has a few limitations. The business folks may request storage for various reasons such as:

  • Recurring subscriptions (often with variable amounts).
  • Customers wanting to keep their card on file for future purchases.
  • Transactional based software providers (such as cloud providers).
  • Customer service wanting to verify the card on file with a customer.
  • Managers wanting to authorize certain charges for employees.

Storage

When storing information as confidential as credit card data, even though its behind multiple passwords and buried in a database, it should be encrypted. PHPs mcrypt library is ideal for this, using a cipher like MCRYPT_RIJNDAEL_256 (AES 128-bit) to encode 32 bytes of data (ideal for a card number and expiration). If youre anything like me, developing a home grown solution means:

  • Researching the various encryption ciphers.
  • Looking into legal requirements.
  • Re-reading PHP's mcrypt function reference.
  • Write a class or extend one with methods to provide encryption and decryption, generating IVs and such.
  • Working with your project's ORM or database libraries to implement the new class or methods for encryption.
  • Build a testing strategy to ensure everything works and continues to work with future development.

CreditCardFreezer

Id prefer not to do this with every implementation, so I decided to write a class called CreditCardFreezer. CreditCardFreezer is a PHP class which automates the storage and retrieval of encrypted credit card information to and from a database.

Although there are plenty of classes and packages (such as those in the Zend framework) for validating credit card numbers or interfacing with payment gateways, I was hard pressed to find anything that deals with encryption and storage of the secure data. With CreditCardFreezer, its as simple as:

 
$obj = new CreditCardFreezer;
$obj->number = '1234-1234-1234-1234';
$encrypted = $obj->setPassKey('super secret')
                 ->get('number', true); // 'ViSxj3...'
 
// Store $encrypted into your database
 
$obj = new CreditCardFreezer;
$number = $obj->set('number', $encrypted, true)
              ->get('number');
echo $number; // 1234123412341234
 

CreditCardFreezer implements both a fluent interface for method chaining as well as an object-based one (shown above) which should be familiar for those who use an ORM like Doctrine. A complete documentation on the usage and syntax can be found here.

CreditCardFreezer is open source and PHPUnit tested. Its released under the BSD license, so youre free to use it as you like. More information can be found on my Github project page.

Features

Some of the features it currently includes are:

  • AES 128-bit encryption through PHP's MCRYPT_RIJNDAEL_256 cipher.
  • CFB mode for random IV generation upon every encryption to prevent patterns in the output.
  • Numerous methods for storing and accessing various attributes used with credit card transactions, including secure attributes like card numbers and unsecured attributes like names and addresses.
  • PDO class which can be used to implement ORM-like functionality to directly store and retrieve data from a database connection (and even create the schema).
  • PHPUnit tested to ensure it works now and after future development.

Your feedback and any ideas or contributions are always welcome, email me at me [at] andrewkandels.com.