A national identity number is a format and sometimes a formula. The format says how many characters it has, which characters are allowed and where any separators go. The formula, when a country publishes one, says that the last character or two are derived from the others by arithmetic, so a number that fails the arithmetic was mistyped or invented.
Understanding the difference between those two things is most of the work. A number whose formula succeeds is not a real person’s document; it is a number whose digits are mutually consistent. Everything below is about that distinction and about the arithmetic families that produce it.
What a check digit is, and what it is not
A check digit is redundancy, and redundancy has a precise value. It catches a single mistyped digit almost every time, and it usually catches two digits that were swapped. That is the whole benefit, and it is a large one: most keying errors are one of those two mistakes.
It catches nothing else. It cannot tell you that a number was issued, that it belongs to the person presenting it, that the person exists, or that the document is genuine. A generated number whose arithmetic works is an internally consistent string, which is exactly what a test fixture needs and exactly what an identity check must not rely on.
The mod 11 family
Most national schemes are variations on one idea. Take the digits in a fixed order, multiply each by a weight from a fixed cycle, add the products, reduce the sum modulo a prime, and map the remainder to a character.
Within that single sentence the country-specific details live, and they are what make copying a neighbouring implementation dangerous. The weight cycle differs. The direction of iteration differs, which matters as soon as the weights are not symmetric. And the handling of the remainders that cannot be expressed as a plain decimal digit differs: some schemes map a remainder of ten to the letter K, some map remainder ten or eleven to zero, and some map the remainder into a letter table indexed by the value.
Three examples show the spread. Brazil’s CPF uses two check digits: the first is computed over the first nine digits and the second over the first ten, each with its own weight sequence. Spain’s DNI takes the numeric part modulo twenty-three and indexes the remainder into a fixed table of letters, so the result is a letter rather than a digit. The Turkish T.C. Kimlik number uses two check digits as well, one derived from the odd-positioned digits and one from the even-positioned digits together with the first ten digits, and it carries a structural rule that the first digit is never zero.
There is a portable lesson hidden in the Turkish example. If the intermediate arithmetic is performed in a language that preserves the sign of the dividend, an intermediate value can go negative before the final reduction, and an implementation written in a language that floors instead can produce a different answer. That is a real class of bug in copy-pasted validators, and it does not announce itself.
Where does the family resemblance break down?
It breaks down the moment anyone assumes uniformity. Two countries both described as mod eleven can disagree on the weight cycle, on whether the check digit is computed left to right or right to left, on whether the check character is a digit or a letter, and on what happens when the remainder is ten.
The practical consequence is that a validator written from a neighbouring country’s source code will accept some invalid numbers and reject some valid ones, and both outcomes look like success at a glance. The only defensible approach is to work from the issuing authority’s published specification, and to keep each country’s implementation separate rather than parameterising one shared function until it fits everything.
Mexico’s CURP illustrates the other direction. It is longer, and it layers several rules: the first characters encode a birth date and a sex and a state code from a fixed table, and the final character is a check value computed over a thirty-seven symbol alphabet that includes the letter Ñ. A validator for it therefore has more than one way to fail, which is the next point.
Several layers of validity
Structure and arithmetic are separate layers, and a well-built pipeline reports which one failed rather than returning a single boolean.
Other schemes with more than one rule include the ones where a portion of the number encodes a date, a region or a category. A social insurance style number may forbid certain ranges entirely, so a number can be structurally well formed and still impossible because no such range was ever allocated.
The overview of check digit algorithms groups the arithmetic families, and the national ID validation rules by country lists which countries publish a rule at all. A useful habit is to normalise first and check last: strip separators, trim whitespace, apply Unicode normalisation and uppercase the result, then check length, then the character set, then the structural rules, and only then the arithmetic. Each stage should fail distinguishably, because a support engineer reading a log entry needs to know which one it was.
What does Luhn catch that mod 11 does not?
Nothing that mod eleven fails to catch, and less. Luhn, the mod ten scheme used by payment cards, works from the right: double every second digit moving leftwards, subtract nine from any result above nine, sum everything and require the total to be divisible by ten.
Its behaviour on transpositions is weaker. Swapping two adjacent digits whose values differ by five, and specifically a zero next to a nine, survives the test, because the doubling pattern does not change the sum in that case. Mod eleven schemes avoid that particular blind spot, which is one reason identity numbers rarely use Luhn.
Luhn also says nothing about whether a card exists, who issued it or whether it is active. The prefix and the length carry the issuer information, and those are separate checks with their own failure modes. The Luhn algorithm page goes into the arithmetic and the exceptions in more detail.
What does valid mean when the field is on a form?
There are three meanings in circulation, and forms conflate them constantly.
The first is that the value has the right shape, which is a formatting question the browser can answer immediately. The second is that the arithmetic works, which needs the country’s rule and is a server-side job. The third is that the number was issued to a real person, which no system can answer without the issuing authority, and which no test fixture should ever claim.
Only the first two are answerable offline, and the honest label for a country with no published algorithm is format only. The United States SSN is the standard illustration: it has a structure, with an area, a group and a serial portion, and a list of patterns that are never allocated, but no published check digit at all. A validator that manufactures one is worse than a validator that admits its limits, because it rejects valid numbers and gives a false sense of rigour.
That is the case the numbers without check digits article makes at length, and it is the reason the validation tool marks such values as format-only rather than implying they passed a rule. The same restraint applies to identity number length, where length is a country fact and not a property of any individual.
Building a boundary test set
Once a validator exists, its tests should be built around the failure boundaries rather than around real-looking numbers.
| Case | Purpose |
|---|---|
| All zeros | Catches implementations that treat zero as a valid special case |
| Length off by one | Separates the length stage from the arithmetic stage |
| Final character altered | The check digit itself, the most common keying error |
| Two adjacent digits swapped | Tests the transposition case the scheme exists to catch |
| Leading zero removed | Catches numeric rather than string handling |
| Separators, spaces, lowercase, full-width | Exercises normalisation before validation |
| Impossible structural range | Tests the layer between the characters and the arithmetic |
Keep the negative cases in the same suite as the positive ones. A validator tested only with values that should pass has an unmeasured failure mode, and the failure mode is usually that it accepts everything.
Fixtures and honesty
When the system under test validates identity numbers, use values whose arithmetic is correct, produced by a tool that implements the published rule rather than pasted from a document. When the system should reject, use deliberately broken values, kept in a set clearly marked as invalid so nobody promotes one into a happy path by accident.
Never use a real person’s number, in any environment, for any reason. The reproducibility that a real number appears to offer is fully available from a pinned synthetic key: the same key and country return the same internally consistent value on every run, which is enough for a regression test and carries no privacy question at all. The country directory shows which countries have a published rule and which are shape only.
Every number described here is fictional example material, not a value belonging to any person, and no arithmetic check in this article establishes that any document was ever issued.