diff --git a/src/us/ssn.ts b/src/us/ssn.ts index a93c76ea..d327bab4 100644 --- a/src/us/ssn.ts +++ b/src/us/ssn.ts @@ -17,7 +17,7 @@ import * as exceptions from '../exceptions'; import { strings } from '../util'; import { Validator, ValidateReturn } from '../types'; -const invalidSSN = [ +const invalidSSNSet = new Set([ '111111111', '222222222', '333333333', @@ -27,7 +27,6 @@ const invalidSSN = [ '888888888', '999999999', '123123123', - '999999999', // Used in Advertising and known "invalid" '002281852', '042103580', @@ -51,7 +50,7 @@ const invalidSSN = [ '457555462', '468288779', '549241889', -]; +]); function clean(input: string): ReturnType { return strings.cleanUnicode(input, '- '); @@ -94,7 +93,7 @@ const impl: Validator = { if (!strings.isdigits(value)) { return { isValid: false, error: new exceptions.InvalidComponent() }; } - if (invalidSSN.includes(value)) { + if (invalidSSNSet.has(value)) { return { isValid: false, error: new exceptions.InvalidComponent() }; } if (/^(000|666|9)\d+/.test(value)) { diff --git a/src/util/checksum.ts b/src/util/checksum.ts index 0e76a469..3f0d4263 100644 --- a/src/util/checksum.ts +++ b/src/util/checksum.ts @@ -80,7 +80,6 @@ export function luhnChecksumValidate( const sum = value .split('') - // .reverse() .map(v => alphabet.indexOf(v)) .reduce((acc, val, idx) => { let v = val; @@ -213,6 +212,25 @@ function modulo(dividentIn: string, divisor: number) { return parseInt(divident, 10) % divisor; } +/** + * Convert a string using alphanumeric alphabet to its numeric representation. + * Returns null if any character is not in the alphabet. + */ +function alphabetToNumber( + value: string, + alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', +): string | null { + let result = ''; + for (const c of value) { + const idx = alphabet.indexOf(c); + if (idx === -1) { + return null; + } + result += String(idx); + } + return result; +} + /** * The ISO 7064 Mod 97, 10 algorithm. * @@ -220,25 +238,10 @@ function modulo(dividentIn: string, divisor: number) { * valid if the number modulo 97 is 1. As such it has two check digits. */ export function mod97base10Validate(value: string, expect = 1): boolean { - const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - let fail = false; - - const bigValue = value - .split('') - .map(c => { - const idx = alphabet.indexOf(c); - if (idx === -1) { - fail = true; - return ''; - } - return String(idx); - }) - .join(''); - - if (fail) { + const bigValue = alphabetToNumber(value); + if (bigValue === null) { return false; } - return modulo(bigValue, 97) === expect; }