I need a reversible, key-based encryption algorithm for credit card numbers. I've done some Googling, and looked around in the PHP documentation, but I haven't found anything that meets my needs.

I could always invoke a PGP executable from my PHP script, but I'd prefer to stay in PHP if I can.

  1. Are there any core PHP functions that do true encryption (not hashing)?

  2. Can anyone recommend a PHP library that provides robust encryption of this sort?

Thanks!

    the problem is not the encryption piece right... it's the decryption piece.

    How I've personally always solved this problem: DONT STORE CREDIT CARD NUMBERS, PERIOD.

    Use your payment gateway provider (authorize.net for example, in order to store the values and pull them whenever you need.)

    that's my suggestion.

    If you seriously have to do this - http://us3.php.net/mcrypt

    but trust me... don't

      I appreciate your concerns, but in the application I'm building, credit cards can't be charged at the time of form submission - they need human review and processing first. So I have to store the numbers one way or another.

      I've decided to use MySQL's AES encryption functions (and, of course, to require an SSL connection for all admin pages in my app, since it'll be displaying card numbers to the admin users). Once the transaction has been processed, I'll update the database record so it only stores the last four digits of the card number.

      Not ideal, but pretty good given the limitations at hand.

      Thanks for the input!

        4 days later
        iceomnia wrote:

        Hi,

        I actualy store card numbers in ywo tables with two differend encryption keys.

        This class is my favorite encryption class, as it's quite simple, but yet quite secure at the same time.

        http://www.tonymarston.net/php-mysql/encryption.html

        Why use a class like that when both PHP and MySQL have built-in encryption functions based upon proven algorithms with a known level of security?

          Why use a class like that when both PHP and MySQL have built-in encryption functions based upon proven algorithms with a known level of security?

          I agree. The author, Tony Marston, states: "The beauty of this method is that even if you know the exact encryption algorithm being used it is totally useless without the key."

          This is true, but it assumes that the encryption algorithm is a good one.

          Tony Marston wrote:

          As you can see it is not impossible to create a reasonable encryption function of your own using standard PHP functions. This way you can have your own customisable routine which does not rely on any 3rd party modules which your web hosting service may not feel inclined to provide.

          A reasonable snake oil encryption function, perhaps. According to his personal website, Tony Marston is a software engineer whose "particular forte is not just the development of end-user software, it is the creation of development infrastructures with which such software can be built". There is no mention of a background in cryptography, so I see no reason to trust that any encryption algorithm he comes up with is secure. Even the experts in the field have made mistakes that only came up after peer review.

            Not to mention, an implementation in C of Rijndael is likely to be quicker than a lot of bumping and grinding in PHP (and more portable too: care to implement Marston's algorithm (is that a one-rotor Enigma machine?) in MySQL? Or some other environment?).

            Oh, and I just noticed this (hey, so I was bored):

            // Do not use single quote, double quote or backslash as these have special meanings in PHP.
                    $this->scramble1 = '! #$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~';
                    ...
            
            $char1 = substr($source, $i, 1);
            
            // identify its position in $scramble1
            $num1 = strpos($this->scramble1, $char1);

            So I can't encrypt "O'Reilly".

              I agree that php and mysql both offer their own encryption functions, however, I access the db from two languages php and c# and in order to ensure I am encrypting and decrypting the data in an identical way I need to ensure that I am using an identical method.

              I use a desktop piece of software to sync sales orders with Sage Accounting etc, and the CC numbers are held in the MySQL database until the point of dispatch.

              In the UK, it is the law that you may "Pre-Authorise" a card at the point of sale, however, you MUST NOT "Finalise" or "RELEASE" (from their account) the funds until point of dispatch.

              HSBC require the authorisation number and the card number in order to do this. Whereas Barclays bank, only require the authorisation number.

              In addition, we can store card numbers for regular customers and it would be very irresponsible to store them without encryption... What's more, a standard base64_encode() is pointless as it's so easy to decode,

              Could someone tell me what base64_encode is actually for, with it having a decode function that does not relay on any key?

                I agree that php and mysql both offer their own encryption functions, however, I access the db from two languages php and c# and in order to ensure I am encrypting and decrypting the data in an identical way I need to ensure that I am using an identical method.

                You might want to just use the encryption provided by the database system. That said, mcrypt should be encrypting such that if you use the same algorithm from C# the decryption should work.

                Could someone tell me what base64_encode is actually for, with it having a decode function that does not relay on any key?

                For encoding, not encryption, "to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies" (according to the PHP manual entry).

                  Write a Reply...