Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Credit Card Encryption

Status
Not open for further replies.

twiSSt

Programmer
Joined
Mar 25, 2004
Messages
282
Location
US
I have a client that we were taking orders and processing the credit card for. Due to changes beyond my control, they are now going to be processing the credit cards themselves.

The current system is not in CF, and I do not want to recreate it,(the client is not going to pay for it), but i can program it to open an URL and then have the person taking the order enter the CC info. There is already a function which can email the rest of the order to the client.

My concern is security, so i am looking for suggestions on how to handle this part of the transaction.

Twist

===========================================
Everything will be OK in the end.
If it's not OK, then it's not the end
 
I'd hash at least part of the credit card number OR write a UDF to scramble the characters in the string so that it would be difficult to decipher without a descramble working in the same order.

ALFII.com
---------------------
If this post answered or helped to answer your question, please reply with such so that forum members with a similar question will know to use this advice.
 
Thanks, but i guess i was not clear in my first post. I know what i want it to look like, like you said hash out everything but the first 4 numbers. I'm not sure how to do so.

I'm assuming that i need to encrypt the cc number in the query that submits to the database.

I've included the code below in case it helps
Code:
INSERT INTO order_info (order_id,cc_type,cc_num,cc_code,cc_month,cc_yr) 
VALUES ('#FORM.order_id#','#FORM.cc_type#','#FORM.cc_num#','#FORM.cc_code#','#FORM.cc_month#','#FORM.cc_yr#')

Twist

===========================================
Everything will be OK in the end.
If it's not OK, then it's not the end
 
See.. here's what I'm thinking.. This solution would work on a 16 digit number.. you could alter it for other lengths..

Code:
<cfset ccnum="1234876595131436">
<cfset hashkey="bluebird">
<cfset chash=hash(mid(ccnum,1,4) & hashkey)>
<cfset chash=chash & "/" & mid(ccnum,5,4))>
<cfset chash=chash & "/" & hash(mid(ccnum,9,4) & hashkey)>
<cfset chash=chash & "/" & mid(ccnum,13,4)>

Now you can store #chash# in the db.. A dehashing routine would be easy enough (even through there is no actual dehash() function). Its a bit load intensive but is secure and you shouldn't need to do it unless you need to re-charge a card.

Code:
<!--- Assuming dbHash is where the hashed number is stored in the db --->
<cfset cThis=queryname.dbhash>
<cfloop from="1" to="4" index="overI">
  <cfloop from="1" to="9999" index="ci">
    <cfif hash(numberformat(ci,"0000") & hashkey) is listgetat(chash,"/",overI)>
      <cfset "c#overI#"=listgetat(chash,"/",overI)>
      <cfbreak>
    </cfif>
  </cfloop>
</cfloop>
<cfset ccNum = c1 & c2 & c3 & c4>

I know it seems overboard, but it would definitely be secure... Note that once you set hashkey, you can't change it.

Code:
<cfscript>
  function Scramble(tString,bMode) {
    if(bMode eq "in") {
       passhalf1 = left(tString,int(len(tString)/2)-1);
       passhalf2 = right(tString,ceiling(len(tString)/2)-1);
       passmid1 = mid(tString,len(passhalf1)+1,1);
       passmid2 = mid(tString,len(passhalf1)+2,1);
       passrev2 = reverse(passhalf2);
       [red]passcomp1 = passmid1 & ReplaceNoCase(passhalf1,passmid1,"!","ALL");
       passcomp2 = passmid2 & ReplaceNoCase(passrev2,passmid2,"!","ALL");[/red]
       passresult = passcomp1 & passcomp2;
       passresult = left(passresult,2) & Reverse(mid(passresult,3,len(passresult)-4) & right(passresult,2));
       return passresult;
    } else if(bMode eq "out") {
       tString = left(tString,2) & Reverse(mid(tString,3,len(tString)-4) & right(tString,2));
       passhalf1 = mid(tString,2,int(len(tString)/2)-1);
       passhalf2 = mid(tString,len(passhalf1)+3,len(tString)-(len(passhalf1)+2));
       passmid1 = left(tString,1);
       passmid2 = mid(tString,len(passhalf1)+2,1);
       passrev2 = reverse(passhalf2);
       passcomp1 = passhalf1 & passmid1;
       passcomp2 = passmid2 & passrev2;
       [red]passcomp1 = ReplaceNoCase(passcomp1,"!",passmid1,"ALL");
       passcomp2 = ReplaceNoCase(passcomp2,"!",passmid2,"ALL");[/red]
       passresult = passcomp1 & passcomp2;
       return passresult;
    } else {
      return "Mode not valid, must be ""in"" (to scramble) or ""out"" (to unscramble).";
    }
  }
</cfscript>

This is less scure but wouldn't be expected so would work just as well.

Just #Scramble(ccnum,"in")# to scramble it..

And then just #Scramble(scrambled_cc_num,"out")# to unscramble..

I'd suspect that if the orig cc number was mod10 compliant that the scrambled version would be too so it would confuse anyone who read the number from the db.

Also you'll notice the red lines. If you leave them, the number is not mod10 compliant BUT it does leave a hacker in the db to wonder what that ! is.

ALFII.com
---------------------
If this post answered or helped to answer your question, please reply with such so that forum members with a similar question will know to use this advice.
 
Thanks for your suggestion, it was very helpful!

Twist

===========================================
Everything will be OK in the end.
If it's not OK, then it's not the end
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top