diff options
Diffstat (limited to 'verhoeff')
-rw-r--r-- | verhoeff/verhoeff.go | 69 | ||||
-rw-r--r-- | verhoeff/verhoeff_test.go | 34 |
2 files changed, 103 insertions, 0 deletions
diff --git a/verhoeff/verhoeff.go b/verhoeff/verhoeff.go new file mode 100644 index 0000000..259a7df --- /dev/null +++ b/verhoeff/verhoeff.go @@ -0,0 +1,69 @@ +package verhoeff + +import ( + "strconv" + "strings" + + "github.com/neonxp/checksum" +) + +var d = [10][10]int{ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + {1, 2, 3, 4, 0, 6, 7, 8, 9, 5}, + {2, 3, 4, 0, 1, 7, 8, 9, 5, 6}, + {3, 4, 0, 1, 2, 8, 9, 5, 6, 7}, + {4, 0, 1, 2, 3, 9, 5, 6, 7, 8}, + {5, 9, 8, 7, 6, 0, 4, 3, 2, 1}, + {6, 5, 9, 8, 7, 1, 0, 4, 3, 2}, + {7, 6, 5, 9, 8, 2, 1, 0, 4, 3}, + {8, 7, 6, 5, 9, 3, 2, 1, 0, 4}, + {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, +} + +var p = [8][10]int{ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + {1, 5, 7, 6, 2, 8, 3, 0, 9, 4}, + {5, 8, 0, 3, 7, 9, 6, 1, 4, 2}, + {8, 9, 1, 6, 0, 4, 3, 5, 2, 7}, + {9, 4, 5, 3, 1, 2, 6, 8, 7, 0}, + {4, 2, 8, 6, 5, 7, 3, 9, 0, 1}, + {2, 7, 9, 3, 8, 0, 6, 4, 1, 5}, + {7, 0, 4, 6, 9, 1, 3, 2, 5, 8}, +} + +var inv = [10]int{0, 4, 3, 2, 1, 5, 6, 7, 8, 9} + +// Check number is correct by luhn algorithm +func Check(number string) error { + c := 0 + numbers := strings.Split(number, "") + l := len(numbers) + for i := l; i > 0; i-- { + ch := numbers[i-1] + num, err := strconv.Atoi(string(ch)) + if err != nil { + return checksum.ErrInvalidNumber + } + c = d[c][p[(l-i)&7][num]] + } + if c != 0 { + return checksum.ErrInvalidChecksum + } + return nil +} + +// Generate checksum (must be added to number at right) +func Generate(number string) (string, error) { + c := 0 + numbers := strings.Split(number, "") + l := len(numbers) + for i := l; i > 0; i-- { + ch := numbers[i-1] + num, err := strconv.Atoi(string(ch)) + if err != nil { + return "", checksum.ErrInvalidNumber + } + c = d[c][p[(l-i+1)&7][num]] + } + return strconv.Itoa(inv[c]), nil +} diff --git a/verhoeff/verhoeff_test.go b/verhoeff/verhoeff_test.go new file mode 100644 index 0000000..7678b1f --- /dev/null +++ b/verhoeff/verhoeff_test.go @@ -0,0 +1,34 @@ +package verhoeff + +import ( + "testing" + + "github.com/neonxp/checksum" +) + +func TestVerhoeff(t *testing.T) { + samples := map[string]error{ + "4561261212345464": checksum.ErrInvalidChecksum, + "A561261212345464": checksum.ErrInvalidNumber, + "758722": nil, + "123451": nil, + "1428570": nil, + "1234567890120": nil, + "84736430954837284567892": nil, + } + for num, result := range samples { + if err := Check(num); err != result { + t.Errorf("Expected %+v actual %+v", result, err) + } + } + + num := "4561261212345467" + checksum, err := Generate(num) + if err != nil { + t.Error(err) + } + numberWithChecksum := num + checksum + if err := Check(numberWithChecksum); err != nil { + t.Errorf("Expected no error actual %+v", err) + } +} |