Un passeport dont la zone de lecture automatique passe tous les chiffres de contrôle inspire confiance. Le calcul tombe juste, le validateur renvoie true cinq fois, et le parcours d'inscription continue. Il vaut la peine de préciser ce que veut dire ce true, car il promet moins qu'il n'y paraît.

Ce guide s'adresse aux développeurs qui construisent des parcours KYC et d'onboarding. Il classe les contrôles de filtrage courants selon ce que les chiffres de contrôle de la MRZ détectent, ce qu'ils ne peuvent pas détecter, et quel autre contrôle couvre chaque angle mort. Toutes les zones ci-dessous sont le spécimen de l'ICAO lui-même, Anna Maria Eriksson d'« Utopia », ou une variante inventée pour cet article. Aucun document réel n'apparaît.

Ceci est le blog de doc.cheap, une API OCR pour passeports et pièces d'identité. Rien de ce qui suit n'en a besoin.

À quoi servent les chiffres

La MRZ est le bloc de majuscules, de chiffres et de caractères de remplissage < en bas de la page de données d'un passeport ou au dos d'une carte d'identité. L'ICAO Doc 9303 lui attribue des chiffres de contrôle : un pour le numéro de document, un pour la date de naissance et un pour la date d'expiration, un pour le numéro personnel facultatif des passeports, et un chiffre composite sur la plus grande partie de la ligne inférieure.

Chaque chiffre est une somme pondérée. Chaque caractère devient un nombre (0–9 valent eux-mêmes, A = 10 jusqu'à Z = 35, < = 0), les nombres sont multipliés par les poids 7, 3, 1 qui se répètent, et la somme modulo 10 donne le chiffre. Comment fonctionnent les chiffres de contrôle de la MRZ détaille le calcul avec un validateur prêt à copier.

Les chiffres ont été conçus pour repérer les erreurs de lecture. Ils n'ont jamais eu pour but de détecter la fraude, et tout ce qui suit en découle.

Ce qu'un chiffre de contrôle détecte

Un seul chiffre erroné. Comme 7, 3 et 1 n'ont aucun facteur commun avec 10, remplacer n'importe quel chiffre d'un champ par un autre chiffre change toujours la somme modulo 10. Un 3 lu comme un 8, un 5 lu comme un 6 : le chiffre du champ ne correspond plus, et le composite non plus.

La plupart des inversions de deux voisins. Si deux caractères adjacents échangent leur place, la somme change de leur différence multipliée par la différence de leurs poids (4, 2 ou 6). Ce n'est un multiple de 10 que si les deux valeurs diffèrent d'un multiple de 5. Ainsi, 98 saisi 89 est détecté, alors que 16 saisi 61 passe inaperçu, tout comme 05 saisi 50.

Dégâts, reflets et ressaisie. C'est là que les chiffres font leurs preuves. Un pli sur un caractère, un reflet sur le film plastique, une personne qui ressaisit une zone à la main : voilà ce qui produit la plupart des données MRZ erronées, et un chiffre en échec est le signal peu coûteux qu'un champ a été mal lu. La bonne réponse est une nouvelle photo, pas un refus.

Là où le calcul est aveugle

Les chiffres ont des angles morts même face à des erreurs de bonne foi, et un parcours de filtrage doit les connaître.

Une lettre lue comme un caractère dont la valeur diffère de 10, 20 ou 30. Prenez le numéro de document du spécimen, L898902C3, dont le chiffre de contrôle est 6. Remplacez le C (valeur 12) par un 2 (valeur 2) : la somme baisse de 10 × 3 = 30, de 316 à 286, et le chiffre reste 6. Le composite, qui couvre les mêmes caractères avec le même poids, passe lui aussi. Des paires comme B et 1, ou C et 2, peuvent se remplacer l'une l'autre sans un bruit.

Les champs qu'aucun chiffre ne couvre. Le nom, l'État émetteur, la nationalité et le sexe échappent à tous les chiffres de champ, et le composite saute aussi la nationalité et le sexe. Un nom mal lu passe sans bruit ; seule une comparaison avec la page imprimée le révèle.

Ce qu'il ne peut pas détecter du tout

Tout ce qui figure dans cette section passe les chiffres de contrôle de la MRZ, par construction.

Un faux document avec une zone cohérente. L'algorithme est public et tient en vingt lignes de code. Quiconque fabrique un faux document calcule correctement les chiffres, car un chiffre faux est la seule erreur que tout lecteur repère gratuitement. Une zone valide dit que la zone a été bien lue. Elle ne dit rien de l'authenticité du document.

Des données copiées sur une personne réelle. Une zone construite à partir du vrai nom, de la vraie date de naissance et du vrai numéro de document de quelqu'un d'autre a des chiffres valides, puisque les données sont réelles. Savoir si la personne devant la caméra est bien cette personne est une autre question : une comparaison faciale avec la photo du document, une détection du vivant, ou une vérification dans la liste des documents perdus et volés d'un émetteur si vous y avez accès.

Un document expiré. La date d'expiration 120415 passe son chiffre de contrôle, et c'est le 15 avril 2012. L'expiration est une règle sur les dates, pas une somme de contrôle : comparez la date à celle du jour. Rappelez-vous que YYMMDD ne porte pas de siècle, décidez-le donc selon le contexte ; le format de date YYMMDD explique comment. Le calculateur de chiffres de contrôle MRZ de ce site signale une date d'expiration passée comme expirée à côté des chiffres, pour que vous voyiez les deux réponses côte à côte.

Une photo substituée. La MRZ ne contient ni image ni empreinte d'image. Une photo remplacée sur la page de données laisse la zone intacte.

Une puce clonée ou modifiée. Sur un passeport à puce, les groupes de données sont signés par l'État émetteur, et vérifier cette signature (Passive Authentication, ICAO Doc 9303 partie 11) est la façon de savoir que les données viennent de l'émetteur. Cela demande une lecture NFC et les certificats de l'émetteur. Une photo de la page, si bonne soit-elle, ne peut pas y répondre. La MRZ fournit seulement la clé d'accès qui sert à ouvrir la puce.

Le contrôle qu'on oublie : la zone face à la page

Un document dit presque tout deux fois : une fois dans la MRZ et une fois dans la zone d'inspection visuelle (VIZ), la page imprimée que lit une personne. Les deux ont été produites ensemble par un même émetteur, donc sur un document authentique et intact, elles concordent.

C'est ce qui rend une incohérence plus intéressante qu'un chiffre en échec. Un chiffre en échec signifie le plus souvent une mauvaise photo. Des chiffres valides à côté d'un nom de famille, d'une date de naissance ou d'un numéro de document imprimés qui disent autre chose signifient qu'un des deux côtés a été mal lu ou modifié après l'impression. Dans les deux cas, c'est un document qu'une personne doit examiner.

La comparaison doit être faite délibérément. Lisez les deux zones, normalisez les valeurs imprimées (dates sous une même forme, noms réduits à de simples majuscules) et comparez champ par champ. Tenez compte de la translittération : un Müller imprimé peut devenir MUELLER ou MULLER dans la zone, selon l'émetteur. La page des formats MRZ indique quels champs porte chaque format, et donc lesquels peuvent être comparés.

Un ordre de filtrage qui tient la route

  1. Forme. Le nombre et la longueur des lignes déterminent TD1, TD2 ou TD3. Une mauvaise forme est une mauvaise lecture.
  2. Chiffres de contrôle. Un échec signifie reprendre la photo, pas refuser.
  3. Zone face à la page. Une incohérence avec des chiffres valides part vers une personne.
  4. Dates. L'expiration face à la date du jour ; la date de naissance face à vos critères d'âge.
  5. Identité. Comparaison faciale et détection du vivant, face à la photo du document.
  6. Authenticité. Vérification de la puce par NFC, ou éléments de sécurité physiques contrôlés par un service conçu pour cela.

Les étapes 1 à 4 sont peu coûteuses et fonctionnent sur n'importe quelle image. Les étapes 5 et 6 sont des produits à part, et aucune quantité d'arithmétique MRZ ne les remplace.

La place de doc.cheap

L'API OCR de passeports de doc.cheap couvre les étapes 1 à 4 et rend compte honnêtement du reste. Sa réponse contient mrz.status : passed, failed ou absent. En cas de failed, mrz.reason indique ce qui n'a pas collé, soit un chiffre (Check digit failed for: document number), soit un désaccord avec la page imprimée (MRZ does not match the visual zone for: surname), car les deux zones sont lues et comparées par défaut. La zone elle-même revient telle quelle dans mrz.lines et mrz.text, pour que vous puissiez recalculer les chiffres dans votre propre code. document.expiry_date, document.is_expired et document.days_remaining répondent à l'étape 4.

C'est un service de reconnaissance, pas de vérification. Son bloc authenticity indique not_checked au lieu de laisser croire à une validation, et les contrôles de photo et de puce restent du ressort des outils conçus pour eux. Pour tester une zone sans écrire de code, collez-la dans le calculateur de chiffres de contrôle MRZ ; il tourne dans le navigateur et affiche chaque chiffre calculé à côté du chiffre imprimé. Si vous choisissez un service hébergé, la comparaison des API OCR de passeports met les prix publiés côte à côte.

Une question pour vous : lequel de ces angles morts votre parcours d'onboarding a-t-il déjà rencontré en pratique ? Dites-le-nous dans les commentaires ci-dessous.