Home > Uncategorized > Creating Fake Credit Card Numbers in c#

Creating Fake Credit Card Numbers in c#

I recently had to create a credit card number generator, nothing nefarious, just we needed unique valid credit card numbers after asking on StackOverflow and getting a less than stellar response (for the first time). I came across something on DarkCoding.Net which did exactly what I wanted but was in Java, I’ve ported it over to c# and I hope you find it useful

Update

I recently rewrote this code. removing a couple of bugs and making it a bit more c# and bit less Java

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace CreditCardNumberGenerator
{
	public class RandomCreditCardNumberGenerator
	{
		/*This is a port of the port of of the Javascript credit card number generator now in C#
		* by Kev Hunter http://kevhunter.wordpress.com
		* See the license below. Obviously, this is not a Javascript credit card number
		 generator. However, The following class is a port of a Javascript credit card
		 number generator.
		 @author robweber
		 Javascript credit card number generator Copyright (C) 2006 Graham King
		 graham@darkcoding.net
		 This program is free software; you can redistribute it and/or modify it
		 under the terms of the GNU General Public License as published by the
		 Free Software Foundation; either version 2 of the License, or (at your
		 option) any later version.
		 This program is distributed in the hope that it will be useful, but
		 WITHOUT ANY WARRANTY; without even the implied warranty of
		 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
		 Public License for more details.

		 You should have received a copy of the GNU General Public License along
		 with this program; if not, write to the Free Software Foundation, Inc.,
		 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
		 www.darkcoding.net
		*/


		public static string[] AMEX_PREFIX_LIST = new[] {"34", "37"};


		public static string[] DINERS_PREFIX_LIST = new[]
		                                            	{
		                                            		"300",
		                                            		"301", "302", "303", "36", "38"
		                                            	};


		public static string[] DISCOVER_PREFIX_LIST = new[] {"6011"};


		public static string[] ENROUTE_PREFIX_LIST = new[]
		                                             	{
		                                             		"2014",
		                                             		"2149"
		                                             	};


		public static string[] JCB_15_PREFIX_LIST = new[]
		                                            	{
		                                            		"2100",
		                                            		"1800"
		                                            	};


		public static string[] JCB_16_PREFIX_LIST = new[]
		                                            	{
		                                            		"3088",
		                                            		"3096", "3112", "3158", "3337", "3528"
		                                            	};


		public static string[] MASTERCARD_PREFIX_LIST = new[]
		                                                	{
		                                                		"51",
		                                                		"52", "53", "54", "55"
		                                                	};


		public static string[] VISA_PREFIX_LIST = new[]
		                                          	{
		                                          		"4539",
		                                          		"4556", "4916", "4532", "4929", "40240071", "4485", "4716", "4"
		                                          	};


		public static string[] VOYAGER_PREFIX_LIST = new[] {"8699"};

		/*
      'prefix' is the start of the 	CC number as a string, any number
		private of digits	'length' is the length of the CC number to generate.
	 * Typically 13 or	16
		*/
		private static string CreateFakeCreditCardNumber(string prefix, int length)
		{
			string ccnumber = prefix;

			while (ccnumber.Length < (length - 1))
			{
				double rnd = (new Random().NextDouble()*1.0f - 0f);

				ccnumber += Math.Floor(rnd*10);

				//sleep so we get a different seed

				Thread.Sleep(20);
			}


			// reverse number and convert to int
         var reversedCCnumberstring = ccnumber.ToCharArray().Reverse();

			var reversedCCnumberList = reversedCCnumberstring.Select(c => Convert.ToInt32(c.ToString()));

			// calculate sum

			int sum = 0;
			int pos = 0;
			int[] reversedCCnumber = reversedCCnumberList.ToArray();

			while (pos < length - 1)
			{
				int odd = reversedCCnumber[pos]*2;

				if (odd > 9)
					odd -= 9;

				sum += odd;

				if (pos != (length - 2))
					sum += reversedCCnumber[pos + 1];

				pos += 2;
			}

			// calculate check digit
			int checkdigit =
				Convert.ToInt32((Math.Floor((decimal) sum/10) + 1)*10 - sum)%10;

			ccnumber += checkdigit;

			return ccnumber;
		}


		public static IEnumerable<string> GetCreditCardNumbers(string[] prefixList, int length,
		                                          int howMany)
		{
			var result = new Stack<string>();

			for (int i = 0; i < howMany; i++)
			{
				int randomPrefix = new Random().Next(0, prefixList.Length - 1);
	
				if(randomPrefix>1)
				{
					randomPrefix--;
				}

				string ccnumber = prefixList[randomPrefix];

				result.Push(CreateFakeCreditCardNumber(ccnumber, length));
			}

			return result;
		}


		public static IEnumerable<string> GenerateMasterCardNumbers(int howMany)
		{
			return GetCreditCardNumbers(MASTERCARD_PREFIX_LIST, 16, howMany);
		}


		public static string GenerateMasterCardNumber()
		{
			return GetCreditCardNumbers(MASTERCARD_PREFIX_LIST, 16, 1).First();
		}

		public static bool IsValidCreditCardNumber(string creditCardNumber)
		{
			try
			{
				var reversedNumber = creditCardNumber.ToCharArray().Reverse();
				
				int mod10Count = 0;
				for (int i = 0; i < reversedNumber.Count(); i++)
				{
					int augend = Convert.ToInt32(reversedNumber.ElementAt(i).ToString());

					if (((i + 1)%2) == 0)
					{
						string productstring = (augend*2).ToString();
						augend = 0;
						for (int j = 0; j < productstring.Length; j++)
						{
							augend += Convert.ToInt32(productstring.ElementAt(j).ToString());
						}
					}
					mod10Count += augend;
				}

				if ((mod10Count%10) == 0)
				{
					return true;
				}
			}
			catch
			{
				return false;
			}
			return false;
		}
	}
}
About these ads
Categories: Uncategorized
  1. Siaynoq
    April 19, 2011 at 3:19 pm

    Hi Kev!

    I’m also using this “generator”, although I have a major problem with it: we are running automated tests a lot of times, and we definitely need _unique_ numbers, but this algorithm seems to generate duplicates very often.

    I haven’t really debugged the code, maybe if you have any immediate proposal how to enhance this piece of code – that would be brilliant.

    If you have no time or mood, obviously I’ll do the debugging myself, just wanted to let you know about my comments :)

    Regards,

    Zoltan

    • Kev Hunter
      April 19, 2011 at 3:27 pm

      Hi Zoltan,

      within the same session should be very easy, at least to give the appearance of uniqueness you could just use the Linq Distinct() statement on the GetCreditCardNumbers() method. This would mean you would only get unique records back, if you need unique numbers across sessions you’ll probably have to insert them into a database or something similar.

      If there are lots of duplicates it may well be to with the random code in lines 80 to 90 in the code sample above.

      hope this helps

      Kev

  2. Siaynoq
    April 20, 2011 at 8:17 am

    Hi Kev,

    Unfortunately using a DB for this is not an option for us.
    So I did my homework and found the following quick solution:

    [...]

    private static string CreateFakeCreditCardNumber(string prefix, int length)
    {
    //sleep so we get a different seed if called multiple times
    Thread.Sleep(20);
    string ccnumber = prefix;

    Random rndGen = new Random();

    while (ccnumber.Length < (length – 1))
    {
    double rnd = (rndGen.NextDouble() * 1.0f – 0f);

    ccnumber += Math.Floor(rnd * 10);
    }

    [...]

    This modification is anyway better coding (result: faster generation), you don't need to recreate Random() if you are using it in the same static function.
    Relocation of the "Sleep" is needed so we indeed use a different seed while creating multiple CC numbers.

    Self-criticism: I particularly don't like the position of Sleep() in my solution, I hate to waste 20ms, even if it's only in the first cycle. So for those tick-maniac, move Sleep() here (in this case, you will HAVE to use *Numbers() method instead of *Number()):

    [..]

    public static IEnumerable GetCreditCardNumbers(string[] prefixList, int length, int howMany)

    [..]

    result.Push(CreateFakeCreditCardNumber(ccnumber, length));
    //sleep so we get a different seed in CreateFakeCreditCardNumber()
    Thread.Sleep(20);

    [..]

    Ideal solution OO-wise would be to change the structure and force the user to create a new instance of this class (like in case of system Random and call Next() to get new CC number), but I like your simple “static” interface, so I guess this is OK like this :)

    Keep up the great work and sorry for the long “comment”, I hope you like it!

    Regards,

    Zoltan

    • Kev Hunter
      April 20, 2011 at 8:21 am

      I couldn’t agree more about the Thread.Sleep in the code, never feels right..

      The whole class could be made much nicer, its a pretty flat copy from the existing java solution Graham King has on his site, we needed something fairly quick for generating credit cards for when I was writing tests, and this is what I came up with.

      Glad you found it useful

      Kev

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 107 other followers

%d bloggers like this: