Generating fake credit card numbers

hacking
In this short article we are going to see how to generate fake credit card numbers that will pass most online validation checks. There's nothing nefarious you can do with this, as a credit card number is far from being sufficient in order to make online payments. But maybe you need to generate some fake credit card numbers for testing purposes, when developing a website for example, in which case I wish you a good reading!

In a follow-up article, I’ll describe another amusing utilization of card number generators.

Theory

Credit card numbers have structure. They can essentially be decomposed into three parts:

  • An issuer identification number (IIN) consisting of 6 (sometimes 8) digits
  • An individual account identifier
  • A single digit checksum known as the check digit

The total length of a card number will depend on the issuer, ranging from 12 to 19. We will call payload the set of all the digits except the checksum (IIN and account identifier). For most of the credit cards out there, the checksum is calculated from the payload using the Luhn algorithm, also known as the mod 10 algorithm. The idea is that a particular computation involving all the digits of the card number should be divisible by ten for the card number to be considered valid, hence the name. We are going to restrict ourselves to American Express, Mastercard and Visa, which all use a mod 10 check digit.

Generation

If you read this article, you will notice that the IIN can contain lots of information, depending on the issuing network. But most of the time, credit card number validators will only perform a Luhn test, and will sometimes check that the IIN is within the right range for the issuer specified by the user. So in practice we won’t care about the IIN substructure, as we only need to select an IIN within the appropriate range. This means that only a few digits of the IIN must be chosen carefully according to the issuer, and all the rest of the payload is chosen at random. You can find a complete list of IIN ranges and card number lengths per issuer here, but for the three types of cards we want to fake, here’s how it goes:

ISSUER              IIN PREFIX    LENGTH

American Express    34 | 37       15
Mastercard          51 - 55       16
Visa                4             13 | 16

So for example, to generate a valid American Express payload, we could start by 34, and choose 1521=12 digits at random (accounting for the 1-digit checksum).

In order to calculate the check digit using the Luhn algorithm, we will consider the digits of the payload N, starting from the right:

(1)N=dndn1d2d1d0

We will replace each second digit d2k, including the rightmost digit d0, by the sum of the digits of 2d2k (putting it another way, we double each digit of even index, and substitute two digits numbers by their digit sum). Then we compute the sum s of the numbers we obtain:

(2)s=i=0nF10(μidi)where μi={1,i1[2]2,i0[2]

with F10 the digit sum base 10. And the check digit c is given by:

(3)c=(10smod10)mod10

The last modulo 10 operation is important, as s can very well be a multiple of 10 (so the Wikipedia article has it wrong, I guess). The complete credit card number N~ is then obtained by concatenating c to the right of the payload:

(4)N~=dndn1d2d1d0c

Example

Say we want to generate an American Express card number. Then N=34123456789123 is a valid payload. Now, let’s run the Luhn algorithm on this:

{di}={3,2,1,9,8,7,6,5,4,3,2,1,4,3}{6,2,2,9,16,7,12,5,8,3,4,1,8,3}{6,2,2,9,7,7,3,5,8,3,4,1,8,3}s=6+2+2+9++3=68c=(1068mod10)mod10=2

Then N~=341234567891232 is a valid American Express card number!

Validation

Now, to validate a credit card number N~ with the Luhn algorithm, there are basically two equivalent options:

  1. You can remove the check digit c from the card number to obtain N, recompute the checksum as above, and check that you obtain the same digit (boring).
  2. Or you can extract c as above, compute s using 2 and check that s+c is divisible by 10.
Proof [click to expand]
We can decompose any s as a multiple of 10 plus a remainder: (5)s=10s10+smod10sN Also note that smod10=smod10mod10. Using this and 3 we have: (6)s+c=(10smod10)mod10+10s10+smod10=(10smod10+smod10)mod10+10s10=10s1010s+c

Example

Here is an example with my credit card number (kidding): N~=5146947790793307. It starts by 51 so it’s a Mastercard number. We have c=7 as the last digit, and so the payload is N=514694779079330. Now we run the Luhn algorithm:

{di}={0,3,3,9,7,0,9,7,7,4,9,6,4,1,5}{0,3,6,9,14,0,18,7,14,4,18,6,8,1,10}{0,3,6,9,5,0,9,7,5,4,9,6,8,1,1}s=0+3+6+9++1=73(1073mod10)mod10=7=c

Or alternatively:

s=73s+c=73+7=800[10]

so the card number is valid.

Practice

Here is a Python implementation of a card number generator. First, let’s write a helper function luhn_sum() that computes the number s, given a series of digits, using 2:

import random
import sys
import string

def luhn_sum(digits):
    s = 0
    for idx, digit in enumerate(map(int, digits)):
        mu = 1 if idx % 2 else 2
        n = mu * digit
        s += n - 9 if n > 9 else n

    return s

Here, we used the fact that every number n in base 10 is congruent to the sum of its digits modulo 9. If n=ab10,18 we have nn9[9]a+b[9] and n91,9, thus n9=a+b. So summing the digits for such numbers is equivalent to subtracting 9. I don’t want to go out of scope, but read about digital roots if this light touch on the heavy subject of modular arithmetics lit a spark of curiosity.

Then, we just need to construct the payload, and compute the check digit using luhn_sum() and 3:

def generate_card(issuer):
    prefixes = {
        "americanexpress": [34, 37],
        "mastercard":      list(range(51, 56)),
        "visa":            [4]
    }

    lengths = {
        "americanexpress": [15],
        "mastercard":      [16],
        "visa":            [13, 16]
    }

    if not issuer in prefixes.keys():
        raise Exception("Unknown issuer")

    # Get a prefix and a card number length at random
    prefix = str(random.choice(prefixes[issuer]))
    length = random.choice(lengths[issuer])
    # Generate a random body
    body_length = length - len(prefix) - 1
    body = ''.join(random.choice(string.digits)
                   for _ in range(body_length))
    # Concatenate prefix and body
    payload = prefix + body

    # Calculate the check digit using Luhn's algorithm
    s = luhn_sum(payload[::-1])
    c = (10 - s % 10) % 10

    # Concatenate check digit
    return payload + str(c)

The length of a Visa credit card number can be either 13 of 16, so we take that into account. In fact, for many issuers this length can vary.

A Luhn check can be implemented this way:

def luhn_check(card_number):
    c = int(card_number[-1])
    s = luhn_sum(card_number[len(card_number)-2::-1])
    return (s + c) % 10 == 0

You can check the card numbers produced by the above code with online validators such as this one, and see for yourself that it works.




The comment section requires the Utterances cookie in order to work properly. If you want to see people's comments or post a comment yourself, please enable the Utterances cookie here.