computer tutorial 


CREDIT CARD SECURITY


This excellent tutorial is the work of NTSA, who has very kindly consented to the TAZ hosting it.

You can find the original post here:
http://www.antionline.com/showthread.php?s=&threadid=230916

Enjoy!

Outline

In this tutorial I am going to cover two types of credit card validation. The first type of validation is a LUHN check. The second validation method that I cover examines the use of a cards.ini text file for credit card type validation.

LUHN checking

Most credit card numbers (including Visa and Mastercard) conform to the LUHN checksum algorithm. You can calculate the last digit of a card number, by examining all the preceeding digits. You cannot tell from this if the card is stolen, but it can be used to check if the user has made a mistake when entering a card number.

In this article I am publishing both my ASP and PHP LUHN checking functions.

Card Type validation

The second type of validation is checking that the selected card type is correct. Each card type - Visa, mastercard etc - has a given length and prefix. For exampe Visa cards have a prefix of 4 and a length of either 13 or 16 characters. Because of this you can validate that the card type that has been selected by the user is accurate.

This part of the code is only provided in ASP - Sorry

A explaination of the LUHN algorithm

Quote:
The following steps are involved in this calculation:

Step 1: Double the value of alternate digits beginning with the first
right-hand digit (low order).

Step 2: Add the individual digits comprising the products obtained in
step 1 to each of the unaffected digits in the original number.

Step 3: Subtract the total obtained in step 2 from the next higher
number ending in 0 [this in the equivalent of calculating the
"tens complement" of the low order digit (unit digit) of the total].
If the total obtained in step 2 is a number ending in zero
(30, 40 etc.), the check digit is 0.

Example:

Account number without check digit: 4992 73 9871

4 9 9 2 7 3 9 8 7 1
x2 x2 x2 x2 x2
----------------------------
18 4 6 16 2

4 + 1 + 8 + 9 + 4 + 7 + 6 + 9 + 1 + 6 + 7 + 2 = 64

70 - 64 = 6

Account number with check digit 4992 73 9871 6

From: http://staff.semel.fi/~kribe/document/luhn.htm


LUHN Check - ASP version

Example Usage

Quote:
CardIsValid = true
if card.luhncheck(p_CardNo) = true then
debug "luhn ok"
else
debug "luhn failed"
CardIsValid = false
end if


The ASP Code!

Code:
'ASP ISO 7812:1987(E) LUHN Checker
   'This function was written by Simon Barnett. (si@ntsa.org.uk)
   'Use and distribution of this software is covered
   'by open source licence (http://www.opensource.org/osd.html).
   'Please include these comments in any distribution.

Function LuhnCheck(p_cardno)

   session("debug") = "false"
  
   if isnumber(p_cardno) = false then
      luhncheck = false
   else
      if len(p_cardno) = 0 then
         luhncheck = false
      else
        
         tot = 0
         chk = right(p_cardno,1)
         p_cardno = left(p_cardno,len(p_cardno)-1)
  
         for n = len(p_cardno) to 1 step - 2
            x = cint(mid(p_cardno,n,1))  * 2
            if len(x) > 1 then
               tot = tot + cint(mid(x,1,1))
               'debug mid(x,1,1)
               tot = tot + cint(mid(x,2,1))
               'debug mid(x,2,1)
            else
               tot = tot + cint(mid(x,1,1))
               'debug mid(x,1,1)
            end if     
         next
  
         for n = len(p_cardno)-1 to 1 step - 2
            tot = tot + cint(mid(p_cardno,n,1))
            'debug mid(p_cardno,n,1)
         next
  
         'debug tot
  
         checkdigit = cint(cstr(cint(left(cstr(tot),1))+1) & "0") - tot
  
         debug "Checkdigit should be "&checkdigit
         debug "Actual Check Digit "&chk
  
         if int(chk) = int(checkdigit) then
            luhncheck = true
         else
            luhncheck = false
         end if
  
      end if
   end if

End Function



LUHN Check - PHP version

Example Usage

Quote:
// <EXAMPLE USAGE>

if(ValidCard($credit_card)) // Pass credit card details without spaces.
{
echo "Valid Card";
}
else
{
echo "Invalid Card";
}


The PHP Code!

Code:
<?php

function ValidCard($credit_card)
/*   PHP ISO 7812:1987(E) LUHN Checker
   This function was written by Simon Barnett. (si@ntsa.org.uk)
   Use and distribution of this software is covered
   by open source licence (http://www.opensource.org/osd.html).
   Please include these comments in any distribution.
*/

{
   $checksum = substr ($credit_card, -1);    // returns checksum
   $restnum = substr($credit_card, 0, strlen($credit_card)-1);
                // returns rest of credit card number

   $calcvals = "";

   for ($i = strlen($restnum)+1; $i >= 0; $i=$i-2) {  
      $calcvals = $calcvals . strval(intval(substr($restnum,$i,1))*2);
   }

   for ($i = strlen($restnum) -2; $i >= 0; $i=$i-2) {  
      $calcvals = $calcvals . strval(intval(substr($restnum,$i,1))*1);
   }

   $calcvals = substr($calcvals,1);
   $count = 0;

   for ($i = 0; $i <= strlen($calcvals); $i++) {
      $count = $count + intval(substr($calcvals,$i,1));
   }

    if(intval(substr(strval((10*(intval(substr(strval
($count),0,1))+1)-$count)),-1))==$checksum)
   {
      return true;
   }
   else
   {
      return false;
   }
}

?>



Checking the type of card (ASP)

I didn't want to hard code the card type information for obvious reasons, not least amongst which is the fact that I'm using code similar to this over a large number of sites, each with their own list of accepted cards. So I stored all the information about the fornat of each of the different credit card companies in an ini file. This ini file is shown below.

The cards.ini file

Quote:
[Visa]
prefix=4
length=13,16

[Mastercard]
prefix=51,52,53,54,55
length=16

[American Express]
prefix=34,37
length=15

[Dinners Club]
prefix=300,301,302,303,304,305,36,38
length=14

[JCB]
prefix=3
length=16

[Discover]
prefix=6011
length=16


Displaying the list of accepted cards

The CardList routine below reads the cards.ini file given above and displays each of the credit card types in a drop down combo box. The returned 'CardType' variable is used validating the card type in the FormatCheck Function.

Code:
Sub CardList()

   cards = split(getcards(),",")
  
   response.write " <select name='CardType' size='1'>"
   response.write "     <option selected value=''><-Please Select-></option>"
  
   n = 0
   on error resume next
   while err.number = 0
      response.write "     <option value='"& cards (n) &"'>"& cards (n) &"</option>"
      n = n + 1
   wend
  
   response.write "   </select>"

End Sub

Function GetCards()

   Dim fso, MyFile
   Set fso = CreateObject("Scripting.FileSystemObject")
   Set MyFile = fso.OpenTextFile(replace(request("inipath"),"*","\"), ForReading)
  
   getcards = ""
   while not myfile.atendofstream
      l = MyFile.ReadLine
      if left(l,1) = "[" then
         if getcards = "" then
            getcards = mid(l,2,len(l)-2)
         else
            getcards = getcards & ","  & mid(l,2,len(l)-2)
         end if
      end if
   wend

End Function


Validating the selected card type

Example Usage

Quote:
CardIsValid = true
if card.formatcheck(p_CardNo,p_CardType) = true then
debug "Format ok"
else
debug "Format failed"
CardIsValid = false
end if


The Code!

Code:
Function FormatCheck(p_CardNo, p_CardType)

   Dim fso, MyFile
   Set fso = CreateObject("Scripting.FileSystemObject")
   Set MyFile = fso.OpenTextFile(replace(request("inipath"),"*","\"), ForReading)
  
   f=0
   debug "Opening Cards.ini file..."
   while not myfile.atendofstream
      l = MyFile.ReadLine
      if left(l,1) = "[" then
         if mid(l,2,len(l)-2) = p_cardtype then
            f = 1
            debug "found " & mid(l,2,len(l)-2)
            prefix = split(trim(replace(MyFile.ReadLine,"prefix=","")),",")
            length = split(trim(replace(MyFile.ReadLine,"length=","")),",")
         end if
      end if
   wend
  
   myfile.close
  
   if f = 0 then
      formatcheck = false
   else
      prefixok = false
      n = 0
      on error resume next
      while err.number = 0
         debug "Check Prefix:" & prefix(n)
         if left(p_cardno,len(prefix(n))) = prefix(n) then
            debug left(p_cardno,len(prefix(n))) &"="& prefix(n)
            if err.number = 0 then
               prefixok = true
            end if
         end if
         n = n +1
      wend
  
      lengthok = false
      n = 0
      on error resume next
      while err.number = 0
         debug "check len: " &  int(length(n))-1
        
         if len(p_cardno) = int(length(n))-1 then
            if err.number = 0 then
               debug len(p_cardno) &"="& int(length(n))-1
               lengthok = true
            end if
         end if
         n = n +1
      wend
  
      if lengthok = true and prefixok = true then
         formatcheck = true
      else
         formatcheck = false
      end if
  
   end if

End Function

Original Tutorial Submitted by nokia for TheTAZZone-TAZForum

Originally posted on March 7th, 2006 here

Do not use, republish, in whole or in part, without the consent of the Author. TheTAZZone policy is that Authors retain the rights to the work they submit and/or post...we do not sell, publish, transmit, or have the right to give permission for such...TheTAZZone merely retains the right to use, retain, and publish submitted work within it's Network.