Luhn’s Algorithm, The Checksum used on Credit Cards

I was working with hardware that was sequential in coming off a production line. Looking at the hardwares’ serial number, I realized the numbers were mostly sequential, with the exception of the suffix on the serial number. I realized that I was looking at numbers suffixed with a checksum. I tried out a few checksum algorithms to figure out which one fit. This was only being done from curiosity.

One algorithm of special interest was Luhn’s algorithm. This is the algorithm that is used with IMEI, credit card numbers, and Canadian social security numbers. It’s a useful public domain algorithm. I’ve collected a few implementations of it here.

C++

bool pasesLuhnCheck(const string& cardNo)
{
    int nDigits = cardNo.length();
 
    int nSum = 0, isSecond = false;
    for (int i = nDigits - 1; i >= 0; i--) {
 
        int d = cardNo[i] - '0';
 
        if (isSecond == true)
            d = d * 2;
 
        // We add two digits to handle
        // cases that make two digits after
        // doubling
        nSum += d / 10;
        nSum += d % 10;
 
        isSecond = !isSecond;
    }
    return (nSum % 10 == 0);
}

C#

    public static bool CheckLuhnParity(string digits)
    {
        bool isValid = false;

        if (!string.IsNullOrEmpty(digits))
        {
            long sum = 0;
            int parity = digits.Length % 2;
            for (int i = 0; i < digits.Length; i++)
            {
                int digit = digits[^(i + 1)] - '0';
                sum += (i % 2 == parity) ? Luhn(digit) : digit;
            }
            isValid = (sum % 10) == 0;
        }
        return isValid;
    }

Kotlin

fun IsValidLuhnString(entry:String): Boolean {
    var sum = 0
    var isSecond = false
    for( i in entry.length-1..0) {
        val multiplier = if(isSecond) { 2} else {1}
        val digit = entry[i].digitToInt() * multiplier
        sum += digit / 10;
        sum += digit % 10
        isSecond = !isSecond
    }
    return (sum % 10) == 0
}

JavaScript

const luhnCheck =( num, radix) => {
    if(radix == null) { 
        radix = 10
    }
    const arr = `${num}`
      .split('')
      .reverse()
      .map(x => Number.parseInt(x, radix));
    const lastDigit = arr.shift();
    let sum = arr.reduce(
      (acc, val, i) =>
        i % 2 !== 0 ? acc + val : acc + ((val *= 2) > 9 ? val - 9 : val),
      0
    );
    sum += lastDigit;
    return sum % 10 === 0;
  };

You can find a JavaScript/HTML implementation of it at https://j2inet.github.io/apps/luhns. Though this example doesn’t engage in any network communication, while I encourage you to try it out, please don’t use your bank card. Better yet, if you want to examine the code locally, there is also a download link on that page that contains all of the source code.


Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Twitter: @j2inet

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.