[prev in list] [next in list] [prev in thread] [next in thread]
List: php-db
Subject: Re: [PHP-DB] Credit Card Encryption
From: Jason Gerfen <jason.gerfen () scl ! utah ! edu>
Date: 2007-12-26 13:33:15
Message-ID: 4772581B.9060804 () scl ! utah ! edu
[Download RAW message or body]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
What I wrote there will work but I would highly recommend recompiling
PHP with the --with-mcrypt --with-mhash switches. The mcrypt libraries
can be found on sourceforge. http://libmcrypt.sourceforge.net
Jason Gerfen wrote:
> I got messaged off list which I don't appreciate.
>
> But, yes PHP5 only or you could replace the lines for PHP4 and on:
>
> $keys[] = mhash( MHASH_SHA1, sha1( $array[$x] ) );
>
> With:
>
> if( !function_exists( mhash ) ) {
> $keys[] = sha1( sha1( $array[$x] ) );
> } elseif( !function_exists( sha1 ) ) {
> $keys[] = md5( md5( $array[$x] ) );
> } else {
> $keys[] = mhash( MHASH_SHA1, sha1( $array[$x] ) );
> }
>
> That will look to see if the 'mhash()', 'sha1()' functions exist and use
> them accordingly. HTH.
>
> Jason Gerfen wrote:
>> Jason Gerfen wrote:
>>> Daniel Brown wrote:
>>>> On Dec 19, 2007 2:41 AM, Keith Spiller <larentium@hosthive.com> wrote:
>>>>> Ok I've done some research and some thinking. What about storing orders in
>>>>> the database (product info and customer info) and then using GnuPG or PGP to
>>>>> send the credit card info to the merchant? This way the credit card
>>>>> information is not stored on the server or in the database but only in
>>>>> printed format by the merchant. Since my client processes all of the credit
>>>>> card orders by hand this seems like an ideal solution.
>>>> I had a client that did offline (manual) processing of credit card
>>>> orders as well. With liability issues and the problems that others
>>>> have already pointed out, storing the credit card information was not
>>>> an option, yet my client still needed some way of having the data
>>>> available offline.
>>>> Consider the following:
>>>> ISSUER LENGTH
>>>> Diner's Club/Carte Blanche 14
>>>> American Express 15
>>>> VISA 13 or 16
>>>> MasterCard 16
>>>> Discover 16
>>>> Security checks aside (like making sure they selected the type of
>>>> card and that it matched the algorithm - VISA beginning with 4 and
>>>> being strlen($_POST['cardnum']) == 13 or 16, MasterCard being 16,
>>>> beginning with 51xx to 55xx, et cetera), I then had a hybrid of
>>>> storage and delivery.
>>>> Mail the first <? rand(4,6); ?> digits to the sales email
>>>> address(es) on file. Three addresses on two domains were used for
>>>> redundancy in this case. Store the remaining digits in the database.
>>>> You could write your own encryption algorithm or use one that is
>>>> publicly-available and reversible (Blowfish is what I was using, at
>>>> 128, key length of 56 lower ASCII characters, padded with 7 on the key
>>>> and four on the output - MD5, SHA1, et al are NOT options here).
>>>> The sales department then received the first digits of the credit
>>>> card number via email, which stated it was an order key. Again, in my
>>> Using the order number as the key is bad practice. Here is a random key
>>> generator that you could use for your public/private keys and still use
>>> the blowfish cipher as your method of encrypting:
>>> <?PHP
>>> function ReadFolder( $folder )
>>> {
>>> if( ( empty( $folder ) ) || ( !is_dir( $folder ) ) ) {
>>> $rand_image = GenerateError( "Couldn't open directory" );
>>> } else {
>>> $rand_image = array();
>>> if( $handle = opendir( $folder ) ) {
>>> while( false !== ( $file = readdir( $handle ) ) ) {
>>> if( $file != "." && $file != ".." && $file != "index.html" &&
>>> !is_dir( $file ) ) {
>>> $rand_image[] = $file;
>>> }
>>> }
>>> closedir( $handle );
>>> }
>>> }
>>> return $rand_image;
>>> }
>>> function MakeSuperRandom()
>>> {
>>> return srand( ( double ) microtime( time() ) * 100000 );
>>> }
>>> function PickRandomImages( $array )
>>> {
>>> $num1 = count( $array );
>>> $num1 = $num1 - 1;
>>> MakeSuperRandom();
>>> $img_num = rand( 3, $num1 );
>>> $image[] = $array[$img_num];
>>> $num2 = count( $array );
>>> $num2 = $num2 - 1;
>>> MakeSuperRandom();
>>> $img_num = rand( 3, $num2 );
>>> $image[] = $array[$img_num];
>>> $num3 = count( $array );
>>> $num3 = $num3 - 1;
>>> MakeSuperRandom();
>>> $img_num = rand( 3, $num3 );
>>> $image[] = $array[$img_num];
>>> return $image;
>>> }
>>> function ChkArray( $array )
>>> {
>>> if( ( empty( $array ) ) || ( count( $array ) > 3 ) ) {
>>> $data = 1;
>>> } else {
>>> $data = 0;
>>> }
>>> return $data;
>>> }
>>> function GeneratePrivKey( $array )
>>> {
>>> if( empty( $array ) ) {
>>> $data = GenerateError( "Missing data for GeneratePrivKey function." );
>>> } else {
>>> for( $x = 0; $x < count( $array ); $x++ ) {
>>> $keys[] = mhash( MHASH_SHA1, sha1( $array[$x] ) );
>>> }
>>> for( $y = 0; $y < count( $keys ); $y++ ) {
>>> if( count( $keys ) == $keys[$y] ) {
>>> $data .= $keys[$y];
>>> } else {
>>> $data .= $keys[$y] . ":";
>>> }
>>> }
>>> }
>>> return $data;
>>> }
>>> function GeneratePubKey( $data )
>>> {
>>> return md5( $data );
>>> }
>>> function EncData( $data, $key )
>>> {
>>> $td = mcrypt_module_open( 'rijndael-256', '', 'ofb', '' );
>>> $iv = mcrypt_create_iv( mcrypt_enc_get_iv_size( $td ), MCRYPT_DEV_RANDOM );
>>> $ks = mcrypt_enc_get_key_size( $td );
>>> @mcrypt_generic_init( $td, $key, $iv );
>>> $encrypted = mcrypt_generic( $td, $data );
>>> echo "<br><b>Ciphered Text using Random Image Hash as Key:</b><pre> " .
>>> $encrypted . "</pre><br>";
>>> @mcrypt_generic_deinit( $td );
>>> @mcrypt_generic_init( $td, $key, $iv );
>>> $decrypted = mdecrypt_generic( $td, $encrypted );
>>> echo "<br><b>De-Ciphered Text using Random Image Hash as Key:</b><pre>"
>>> . $decrypted . "</pre>";
>>> @mcrypt_generic_deinit( $td );
>>> @mcrypt_module_close( $td );
>>> }
>>> // to use functions
>>> $x = ReadFolder( "images/" );
>>> $y = PickRandomImages( $x );
>>> $b = GeneratePrivKey( $y );
>>> echo "<b>Private Key data:</b><pre>" . $b . "</pre>";
>>> $data = "<br>" . GeneratePubKey( $b );
>>> echo "<b>Public Key data:</b><pre>"; print_r( $data ); echo "</pre>";
>>> echo EncData( $credit_card_data, $b );
>>> ?>
>>> With that code you will have to re-write the 'EncData()' function to
>>> perform ONLY encryption as of right now it encrypts and decrypts for
>>> demonstration purposes only.
>>> And on another note why not use a different delivery method altogether
>>> such as using java-script to encrypt the data prior to transmission,
>>> store the private key inside the local network, use the public key and
>>> associate it with the purchase within the database and develop a method
>>> of authentication for the users to retrieve the data and then, and only
>>> then use the private key to decrypt the data.
>
>> My apologies, I just noticed you did mention a database for storage. SSL
>> would probably work better then java-script. Hell if you really wanted
>> to secure the data prior to transmission using flash might help obscure
>> the data and give you a good method of assigning a unique private/public
>> key as well as passing it through your cipher prior to transmission.
>
>> The kerberos authentication protocol does a similar method prior to
>> sending the data which is always the most secure against eves droppers
>> and man in the middle attacks.
>
>>> Just a thought.
>>>> case, I wrote an algorithm that would encrypt these digits prior to
>>>> sending, using the actual order number as a key. The accounting
>>>> software I wrote (all in PHP) would then retrieve the latter half of
>>>> the credit card number from the database, decrypt the first part of
>>>> the credit card number from the email (entered by the sales team on an
>>>> SSL-encrypted page), and the credit card number would be displayed in
>>>> full on the screen, to print, process, or verify.
>>>> The downside is that, if there are any problems with email and
>>>> delivery, the first $n digits of the card might not be received by the
>>>> sales department. While, to date, I'm not aware of this having been a
>>>> problem for my client (knock on wood), it's still a possibility. For
>>>> this reason, you need to be sure to either have the email address
>>>> confirmed prior to processing the order, or require a valid telephone
>>>> number, so that you can reach the customer in the event of a failure.
>>>> To assure the customer that you are calling legitimately, you will
>>>> still have the last digits of the credit card, as well as the
>>>> expiration data and CVV number (also stored in the database), the
>>>> billing address, and the date and time the order was placed.
>>>> It may not work for you, but that's how I created the system for
>>>> my client in 2004, and it's still being used today, with almost $8
>>>> Million in online sales. [pats self on back] ;-P
>>>> Now if I could just go back and renegotiate my contract for that gig....
>
>
>
- --
Jason Gerfen
"I practice my religion
while stepping on your
toes..."
~The Ditty Bops
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFHclgb5vk8bwKVAaIRAtd5AJ9d4hsO/In8Fdr8uRN/mq7KhHtrpACfYqAK
Lyi5IqnvtfrTsBT2WQvqgL0=
=ge1D
-----END PGP SIGNATURE-----
--
PHP Database Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic