anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

commit 7358b27a289c4899a3de32852e72f5145a6bcb6b
parent 047035bf58e4fec5d5c9f6b3f449d8e36e724ebb
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 29 Jul 2026 18:55:25 +0200

accept Corsican NIR numbers in the French identity check

Diffstat:
Mcontrib/redux.fr.json | 2+-
Msrc/reducer/test_validation.c | 28++++++++++++++++++++++++++++
Msrc/reducer/validation_FR_INSEE.c | 19++++++++++++++++++-
3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/contrib/redux.fr.json b/contrib/redux.fr.json @@ -30,7 +30,7 @@ "tooltip": "Code Insee", "widget": "anastasis_gtk_ia_insee_fr", "uuid": "2f36a81c-3f6d-41f3-97ee-9c885bc41873", - "validation-regex": "^[0-9]{15}$", + "validation-regex": "^[0-9]{5}([0-9]{2}|2[AB])[0-9]{8}$", "validation-logic": "FR_INSEE_check" } ] diff --git a/src/reducer/test_validation.c b/src/reducer/test_validation.c @@ -140,6 +140,34 @@ main (int argc, return 1; } + /* French NIR: mainland and both Corsican department codes. 2A must map to + 19 and 2B to 18, so the two must not produce the same check digits. */ + if (! FR_INSEE_check ("180057512345627")) + { + GNUNET_break (0); + return 1; + } + if (! FR_INSEE_check ("180052A12345684")) + { + GNUNET_break (0); + return 1; + } + if (! FR_INSEE_check ("180052B12345614")) + { + GNUNET_break (0); + return 1; + } + if (FR_INSEE_check ("180052A12345614")) /* 2B's key on a 2A number */ + { + GNUNET_break (0); + return 1; + } + if (FR_INSEE_check ("180052C12345684")) /* no such department letter */ + { + GNUNET_break (0); + return 1; + } + /* AL_NID_check has no implementation yet and deliberately accepts everything; when it is implemented, this expectation must change. */ if (! AL_NID_check ("I05101999I")) diff --git a/src/reducer/validation_FR_INSEE.c b/src/reducer/validation_FR_INSEE.c @@ -29,7 +29,8 @@ * See https://en.wikipedia.org/wiki/INSEE_code * * Note that we do not implement checks on the month - * and also allow non-binary prefixes. + * and also allow non-binary prefixes. Corsican numbers carry 2A or 2B in + * the department field and are accepted. * * @param insee_number social security number to validate (input) * @return true if validation passed, else false @@ -52,6 +53,22 @@ FR_INSEE_check (const char *insee_number) insee_number, 13); pfx[13] = '\0'; + /* Corsica carries a letter in the department field (positions 5-6): the + official rule is to substitute 2A -> 19 and 2B -> 18 before the mod-97, + since the remaining digits alone would collide between the two. */ + if ('2' == pfx[5]) + { + if ('A' == pfx[6]) + { + pfx[5] = '1'; + pfx[6] = '9'; + } + else if ('B' == pfx[6]) + { + pfx[5] = '1'; + pfx[6] = '8'; + } + } if (1 != sscanf (pfx, "%llu%c",