jakub holý

building the right thing, building it right, fast

How To Generate A Valid Credit Card Number For A Bin (First 6 Digits)

2014-03-25 11:45:57General

There is plenty of generators that can produce numbers that are valid credit card numbers according to the Luhn check and specific rules of the individual issuer companies. However I have not found anything that would generate the missing digits given a bin, i.e. the first 6 digits of a credit card (the "bank identification number"). So I created one, reverse-engineering org.apache.commons.validator.routines.CreditCardValidator from common-validator 1.4:


// Groovy:
/** Map RegExp from C.C.Validator to the total length of the CC# */
binReToLen = [
        (~/^(3[47]\d{0,13})$/) : 13+2, // amex
        (~/^30[0-5]\d{0,11}$/) : 11+3, // diners 1
        (~/^(3095\d{0,10})$/) : 10+4, // diners 2
        (~/^(36\d{0,12})$/) : 12+2,     // diners 3
        (~/^|3[8-9]\d{0,12}$/) : 12+2,  // diners 4
        (~/^(5[1-5]\d{0,14})$/) : 14+2, // master
        (~/^(4)(\d{0,12}|\d{15})$/) : 12+1 // visa
        // Discover cards omitted
]

/** Bin is e.g. 123456 */ def completeCCn(String bin) { def ccnFill = "1" * 19 int ccnLen = lenForBin(bin)

def ccnWithoutCheck = bin + ccnFill[0..<(ccnLen - 6 - 1)] // - bin, - check digit

def check = computeLuhncheckDigit(ccnWithoutCheck)

return "$ccnWithoutCheck$check" }

def lenForBin(String bin) { def match = binReToLen.find { it.key.matcher(bin).matches() } if (match == null) { throw new RuntimeException("Bin $bin does not match any known CC issuer") } match.value }

def computeLuhncheckDigit(def ccnWithoutCheck) { org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit.LUHN_CHECK_DIGIT.calculate(ccnWithoutCheck) }

completeCCn('465944') // => 4659441111118


Testing FTW!