Home » PHP/MySQL » Credit Card Encryption and Decryption PHP

This is basically not a tutorial. Here is a ready-made code-piece you can use in your program if you need to store credit card numbers in your database while processing it for payments. If you ever need to store credit card numbers in your database, it should be encrypted before inserting in to the database. PHP has a library called Mcrypt which makes encryption/decryption extremely easy to implement. Mcrypt supports a wide variety of encryption mode and algorithms depending on your needs. I have used “TRIPLEDES” algorithm here with ECB which is good enough to encrypt and protect credit card numbers. You can use hashes such as MD5 to encrypt data, but remember that those are just for one way encryption and it’s for later comparison of data. Mcrypt allows people to easily encrypt AND decrypt information.

Below are the encryption and decryption functions. Pass your credit card number in string format to the encryptCard function and you will get the encrypted code which you can safely store in your database. The important thing here is the KEY. Define a secret string as the $key value which is needed to decrypt the data back to the original value.

function encryptCard($creditno){
	$key = 'YOURSECRETKEY'; //Change the key here
	$td = mcrypt_module_open('tripledes', '', 'cfb', '');
	srand((double) microtime() * 1000000);
	$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
	$okey = substr(md5($key.rand(0, 9)), 0, mcrypt_enc_get_key_size($td));
	mcrypt_generic_init($td, $okey, $iv);
	$encrypted = mcrypt_generic($td, $creditno.chr(194));
	$code = $encrypted.$iv;
	$code = str_replace("'", "\'", $code); //Make sure that the code is not escaped already.
	return $code;
function decryptCard($code){
	$key = 'YOURSECRETKEY'; // use the same key used for encrypting the data
	$td = mcrypt_module_open('tripledes', '', 'cfb', '');
	$iv = substr($code, -8);
	$encrypted = substr($code, 0, -8);
	for ($i = 0; $i < 10; $i++) {
		$okey = substr(md5($key.$i), 0, mcrypt_enc_get_key_size($td));
		mcrypt_generic_init($td, $okey, $iv);
		$decrypted = trim(mdecrypt_generic($td, $encrypted));
		$txt = substr($decrypted, 0, -1);
		if (ord(substr($decrypted, -1)) == 194 && is_numeric($txt)) break;
	return $txt;

I suggest storing the encrypted data in a BLOB field in your MySQL database, which is similar to a TEXT but BLOB stores text string as a binary data. Sorting and comparison is performed in case-sensitive fashion for BLOB values and case-insensitive fashion for TEXT values. BLOB values have no character set, and sorting and comparison are based on the numeric values of the bytes in column values. Hence, a direct string match is not possible in a BLOB field.


  1. Thanks for providing the brilliant code for the encryption and decryption of credit card data.

    You saved my hours!

  2. Aneeska says:

    My pleasure Anil :-) Have fun!

  3. Dear,

    While using you code, One day I found that some cards are not encrypted properly. I am using PDO library. After hours of efforts I found that there is no need of

    $code = eregi_replace(“‘”, “\’”, $code);

    in encryptCard funcion when using PDO, as PDO will itself escape the single quotes. I removed that line and everything was perfect.

    and Without PDO also, you should use str_replace which is much faster that eregi (deprecated now a days).

    Thanks for this code again.

  4. Aneeska says:

    Dear Anil,

    I absolutely agree with you on using str_replace instead of eregi. I just updated my code.
    Thanks for sharing your findings when used with PDO. I have added a comment in the line for other users to consider.


  5. Anil Konsal says:


    I need help in the Recurring Payment through credit card. Can i use the cron job to do that ?

  6. Aneeska says:

    You are never supposed to store the CVV numbers in your database. You are allowed to store credit card numbers encrypted if you adhere to international PCI (payment card industry) compliance standards for data security.

    Almost all online payment systems provide this features with an additional cost. You can use Paypal (https://www.paypal.com/pdn-recurring) or any other Payment Gateways for this. Additionally you can think about using Online Shopping Cart Softwares like UltraCart and configure to use with any of the supporting Gateways.

    Please let me know if you have any questions.


  7. TC says:

    Hi Anees,

    Using this code, I encrypted a number that included dashes, and it doesn’t decrypt properly. The decrypted number contains some of the original digits, but the rest is gibberish. What can I do to decrypt this number?


  8. Aneeska says:

    Hello Andrew,

    I use this function just to encrypt a credit card number and you can notice if (ord(substr($decrypted, -1)) == 194 && is_numeric($txt)) break; this line in the code. The second condition checks whether the value is a numeric. You can remove that condition and it will work for you.

    if (ord(substr($decrypted, -1)) == 194) break;


  9. TC says:

    Thanks Anees, but I already modified the code to show all the decryption attempts from $i = 0 to $i = 9. But in some cases the numbers can’t be decrypted.

    Can you think of anything that would cause this?

  10. Nate says:

    So I am trying to test this out. I am somewhat of a beginner with PHP. Is it possible to echo out the encrypted card number? I’m not getting anything. Thanks.

  11. Nate says:

    Never mind, it was an issue with my test server. It seems to be encrypting, but when I attempt to decrypt, I get gibberish all over again. It’s not returning it to the original number.

  12. Nishita says:

    Great work Aneeska, it really proved helpful.

  13. mike says:

    hi Aneeska ,please Develop 1 software for me. i urgently need Software for Decryption Credit Card Data Track 1 , Track 2.& offset Pin Must show in Software…if you can please Reply me Soon…Thanks

  14. sarmen says:

    hi, thanks for your posting. i was testing it and i found a bug. i made a small php script whose text value has a test cc value and a button and when you press it you get outputted the encrypted value and the decrypted value. if the decrypted value isn’t matched it says no match. keep pressing the submit button a few times and you will notice that it says not matched.


    email me at: sarmenhb@gmail.com

  15. brett says:

    Hi thanks for the great script. I know this is old, but I have a small problem with it sometimes.Was hoping someone could shed some light on it.

    Card Number Entered: 9999999999999999
    Encrypted Value is: ”WÂ9a|Ä>;–x?G ëŠ¢t\’]Ù1Ñ
    Decrypted Value is: #ˆ;á~ðÍTS”¤\£ß

    The decrypted value does not match what was entered. if i refresh the page:

    Card Number Entered: 9999999999999999
    Encrypted Value is: Lâs²ÃÅ´Ö7Fïæ3!²+v¯`¥ðØ
    Decrypted Value is: 9999999999999999

    Every so often, This happens. If i refresh the page, it shows correctly, but happens every 10-15 times i refresh. Any ideas?

  16. Aneeska says:

    Sorry guys. I see that many have issues with this code. I will do a test, fix the possible issue and update you soon.


  17. techman says:

    This is an awesome script. It has saved me hours of work. Thank you so much.

  18. Great script, but sometimes a credit card number will come back up scrambled. It appears random. If I change the credit number repeatedly, one out of ten times it comes back messed up.

    To fix this problem, I save the scrambled number in the database then read it back out. Then I compare the number from the database with my original credit card number. If they do not match, then I do it all again. This prevents the random error from messing up my data.

    Otherwise it is great. Thanks a lot.

Leave a Reply

Page optimized by WP Minify WordPress Plugin