Skip to content

Commit

Permalink
fix: correct checksum for Taiwan ID numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
koblas committed Dec 4, 2023
1 parent a860a9a commit e1aae3a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 20 deletions.
19 changes: 16 additions & 3 deletions src/tw/natid.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ describe('tw/natid', () => {
expect(result).toEqual('00501503');
});

it('validate:A200501503', () => {
const result = validate('A200501503');
it('validate:A200501505', () => {
const result = validate('A200501505');

expect(result.isValid && result.compact).toEqual('A200501503');
expect(result.isValid && result.compact).toEqual('A200501505');
});

it('validate:12345', () => {
Expand All @@ -25,4 +25,17 @@ describe('tw/natid', () => {

expect(result.error).toBeInstanceOf(InvalidComponent);
});

test.each(['A200501503', 'A800501509', 'A800501509'])('not-valid:', value => {
const result = validate(value);
expect(result.isValid).toEqual(false);
});

test.each(['A800000014', 'A123456789', 'A100501503', 'A200501505'])(
'valid:',
value => {
const result = validate(value);
expect(result.isValid).toEqual(true);
},
);
});
16 changes: 10 additions & 6 deletions src/tw/natid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const impl = {
if (!strings.isalpha(issuer)) {
return { isValid: false, error: new exceptions.InvalidComponent() };
}
if (!['1', '2'].includes(gender)) {
if (!/[1-28-9]/.test(gender)) {
return { isValid: false, error: new exceptions.InvalidComponent() };
}
if (!strings.isdigits(code)) {
Expand All @@ -82,11 +82,15 @@ const impl = {
return { isValid: false, error: new exceptions.InvalidComponent() };
}

const sum = weightedSum(value, {
weights: [1, 9, 8, 7, 6, 5, 4, 3, 2, 1],
alphabet: ALPHABET,
modulus: 10,
});
const leading = ALPHABET.indexOf(issuer) - 10;
const sum =
weightedSum(`${gender}${code}${check}`, {
weights: [8, 7, 6, 5, 4, 3, 2, 1, 1],
alphabet: ALPHABET,
modulus: 10,
}) +
Math.floor(leading / 10 + 1) +
leading * 9;
if (sum % 10 !== 0) {
return { isValid: false, error: new exceptions.InvalidChecksum() };
}
Expand Down
21 changes: 16 additions & 5 deletions src/tw/ui.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ describe('tw/ui', () => {
expect(result).toEqual('00501503');
});

it('validate:A800501509', () => {
const result = validate('A800501509');
it('validate:AB00501503', () => {
const result = validate('AB00501503');

expect(result.isValid && result.compact).toEqual('A800501509');
expect(result.isValid && result.compact).toEqual('AB00501503');
});

it('validate:A800501508', () => {
const result = validate('A800501508');
it('validate:AD00501509', () => {
const result = validate('AD00501509');

expect(result.error).toBeInstanceOf(InvalidChecksum);
});
Expand All @@ -35,4 +35,15 @@ describe('tw/ui', () => {

expect(result.error).toBeInstanceOf(InvalidComponent);
});

// additional tests
test.each(['A200501503', 'A800501509', 'CC00151113'])('not-valid:', value => {
const result = validate(value);
expect(result.isValid).toEqual(false);
});

test.each(['AB12345677', 'CC00151114', 'AB00501503'])('valid:', value => {
const result = validate(value);
expect(result.isValid).toEqual(true);
});
});
16 changes: 10 additions & 6 deletions src/tw/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const impl = {
if (!strings.isalpha(issuer)) {
return { isValid: false, error: new exceptions.InvalidComponent() };
}
if (!['A', 'B', 'C', 'D', '8', '9'].includes(gender)) {
if (!/[A-D]/.test(gender)) {
return { isValid: false, error: new exceptions.InvalidComponent() };
}
if (!strings.isdigits(code)) {
Expand All @@ -84,11 +84,15 @@ const impl = {
return { isValid: false, error: new exceptions.InvalidComponent() };
}

const sum = weightedSum(value, {
weights: [1, 9, 8, 7, 6, 5, 4, 3, 2, 1],
alphabet: ALPHABET,
modulus: 10,
});
const leading = ALPHABET.indexOf(issuer) - 10;
const sum =
weightedSum(`${gender}${code}${check}`, {
weights: [8, 7, 6, 5, 4, 3, 2, 1, 1],
alphabet: ALPHABET,
modulus: 10,
}) +
Math.floor(leading / 10 + 1) +
leading * 9;
if (sum % 10 !== 0) {
return { isValid: false, error: new exceptions.InvalidChecksum() };
}
Expand Down

0 comments on commit e1aae3a

Please sign in to comment.