Wednesday, January 2, 2008

PowerShell LUHN validation

 

I came across an interesting security post on Detecting Credit Card Numbers in Network Traffic. Section 2.3 caught my eye and 2 seconds later I was on WIKI's Luhn algorithm page. Soon enough I found myself converting the code to PowerShell. So, pull out your credit card and check its number.

 

#######################################################
## Returns true if the given array of digits represents
## a valid Luhn number, and false otherwise. function Test-LuhnNumber([int[]]$digits){ [int]$sum=0 [bool]$alt=$false for($i = $digits.length - 1; $i -ge 0; $i--){ if($alt){ $digits[$i] *= 2 if($digits[$i] -gt 9) { $digits[$i] -= 9 } } $sum += $digits[$i] $alt = !$alt } return ($sum % 10) -eq 0 }
####################################################### ## Generates a number that passes the Luhn algorithm function New-LuhnNumber([int]$length){ $random = new-object random $digits = new-object int[] $length for($i = 0; $i -lt $length - 1; $i++){ $digits[$i] = $random.next(10) } [int]$sum = 0; [bool]$alt = $true for($i = $length - 2; $i -ge 0; $i--){ if($alt){ [int]$temp = $digits[$i] $temp *= 2 if($temp -gt 9){ $temp -= 9 } $sum += $temp } else { $sum += $digits[$i] } $alt = !$alt } [int]$modulo = $sum % 10 if($modulo -gt 0) { $digits[$length-1] = (10 - $modulo) } return $digits }

## testing...
PS > Test-LuhnNumber (0..9) False
PS > Test-LuhnNumber (New-LuhnNumber 10)
True
PS > Test-LuhnNumber (New-LuhnNumber 15)
True
PS > Test-LuhnNumber (4,4,6,6,6,7,6,5,1)
True
PS > Test-LuhnNumber @(2,8,6,3,7,7,1,1,2)
False
PS > Test-LuhnNumber @(0,6,6,2,4,9,1,8,9,2,3)
True
PS > Test-LuhnNumber "0","6","6","2","4","9","1","8","9","2","3"
True
PS > Test-LuhnNumber ([string[]][char[]]"67276171468")
True
 

4 comments:

Doug Finke said...

Good stuff.
Reduce your keystrokes
with the ql function (thanks to Bruce Payette)

function ql{$args}

test-luhnnumber (ql 0 6 6 2 4 9 1 8 9 2 3)

Anonymous said...

Great snippet, thanks! Helped me generate 9 digit National Provider Ids, just had to add 24 to the sum.

Anonymous said...

Great job! I needed this

Jesse said...

Added the following two lines to the top of the Test-LuhnNumber function for ease of input, so you can just directly enter numbers or strings instead of manually splitting:

if($digits -is [string]){$digits = ([string[]][char[]]$digits) }
if($digits -is [int64]){$digits = ([int[]](($digits -split '') -ne '')) }