# [thelist] Developing secure sites and waiving liability

Keith cache at dowebscentral.com
Tue Jul 16 13:34:01 CDT 2002

```At 10:03 AM Tuesday 7/16/2002, Judah wrote:

>That's really interesting.  I wasn't aware of that.  Do you have any
>good links that explain how and why the last 4 digits are generated from
>the first 12?

Actually it's more correct to say that the last 4 are generated to match
the first 12.

Any credit card number can be tested for valid format using the Luhn test.
Luhn is a mod10 algorithm that tests the card number for valid number
structure. The idea is that a card number containing a 1 digit typo error
should fail the Luhn test, alerting the user to re-enter the card number.
With that kind of stricture built in to all card numbers the number of
possible last 4 digits that can successfully match the first 12 is really
quite small. Below is a javascript mod10 test authored by Netscape in 1995
(the Luhn test has been in effect since the '60s). If you enter a valid cc
number and then start changing digits you'll quickly see what I mean when I
say there is only a limited number of possibilities for the last 4 digits.

Years ago I used this same algorithm in a loop from 0000 to 9999 to capture
all passable last 4 digits for my own credit card - there are only 87 that
passed the test. Someone possessing my first 12 digits can likewise
generate those same 87 sets and be a lot closer to using the card. Go on a
pay-for-access site and start entering the cc numbers to live authorization
and they can find out which of those 87 were actually issued to current
cards.  Considering all this, it's probably a good idea to also email the
expiration month and year with the last digit string instead of saving it
on the server with the front digit string.

<Netscape Luhn test>

<html>
<title>Luhn Test</title>
<script language=javascript>
function isCreditCard(st) {
if (st.length > 19)
return (false);
sum = 0; mul = 1; l = st.length;
for (i = 0; i < l; i++) {
digit = st.substring(l-i-1,l-i);
tproduct = parseInt(digit ,10)*mul;
if (tproduct >= 10)
sum += (tproduct % 10) + 1;
else
sum += tproduct;
if (mul == 1)
mul++;
else
mul--;
}
if ((sum % 10) == 0)
return (true);
else
return (false);
}
function isAnyCard(cc){
if (!isCreditCard(cc)){
YOUR CREDIT CARD NUMBER\n\nEnter no dashes, spaces\nor other punctuation\n");
document.forms[0].cardnum.value=""
}               }
</script>
<body>
<form>
<input size=16 name=cardnum value="" onchange="isAnyCard(this.value)">
</form>
</body>
</html>

</Netscape Luhn test>

Keith
====================
cache at dowebscentral.com

```