Josep Portella
Desmitificant els números del DNI
Setembre de 2005
Actualitzat: juliol i agost de 2011
Traduït: març de 2012
Aquesta obra està sota una llicència de
Reconeixement-SenseObraDerivada 3.0 Creative Commons.
Contingut
Introducció
Tots ens hem fixat alguna vegada en els misteriosos caràcters que hi ha a la part posterior del nostre DNI:
IDESPABC123456012345678Z<<<<<<
7410150M0903226ESP<<<<<<<<<<<9
DE<TAL<I<QUAL<<TAL<ALTRE<<<<<<
Existeix un mite que diu que el darrer dígit de la segona línia indica el número de persones que tenen el mateix nom i cognoms que el portador. La finalitat d'aquest article és demostrar que no és així.
Aquesta zona del DNI està composta per caràcters OCR, és a dir, està preparada per a ser llegida per màquines. Aquest dígit en concret és tan sols un dígit de control per verificar que s'han llegit correctament les dades.
A continuació s'identificaran cada un dels camps que formen la zona de dades OCR i s'explicarà l'algorisme utilitzat pel càlcul dels dígits de control.
Identificació dels camps
La zona de dades OCR del DNI electrònic es pot dividir en diversos camps:
1.[ID] 2.[ESP] 3.[ABC123456] 4.[0] 5.[12345678Z] 6.[<<<<<<]
7.[741015] 8.[0] 9.[M] 10.[090322] 11.[6] 12.[ESP] 13.[<<<<<<<<<<<] 14.[9]
15.[DE<TAL<I<QUAL<<TAL<ALTRE<<<<<<]
- Tipus de document
- Nació
- Número de sèrie del suport físic de la targeta
- Dígit de control del camp 3
- Número de DNI
- Farciment
- Data de naixement (
AAMMDD
) - Dígit de control del camp 7
- Sexe (
M
/F
) - Data de caducitat
- Dígit de control del camp 10
- Nacionalitat
- Farciment
- Dígit de control dels camps 3, 4, 5, 7, 8, 10 i 11 concatenats
- Nom
Al DNI tradicional els camps son diferents:
1.[ID] 2.[ESP] 3.[12345678Z] 4.[3] 5.[<<<<<<<<<<<<<<<]
6.[741015] 7.[0] 8.[M] 9.[090322] 10.[6] 11.[ESP] 12.[<<<<<<<<<<<] 13.[4]
14.[DE<TAL<I<QUAL<<TAL<ALTRE<<<<<<]
- Tipus de document
- Nació
- Número de DNI
- Dígit de control del campo 3
- Farciment
- Data de naixement (
AAMMDD
) - Dígit de control del camp 6
- Sexe (
M
/F
) - Data de caducitat
- Dígit de control del camp 9
- Nacionalitat
- Farciment
- Dígit de control dels camps 3, 4, 6, 7, 9 i 10 concatenats
- Nom
Càlcul dels dígits de control
Els dígits de control es generen a partir d'altres camps al quals
se'ls aplica un algorisme senzill. Primer s'ha de separar per
caràcters, per exemple, si el valor del camp és 12345678Z
:
1 2 3 4 5 6 7 8 Z
Si algun dels caràcters és una lletra, s'ha de canviar pel seu valor numèric:
A 0 F 5 K 10 P 15 U 20 Z 25
B 1 G 6 L 11 Q 16 V 21
C 2 H 7 M 12 R 17 W 22
D 3 I 8 N 13 S 18 X 23
E 4 J 9 O 14 T 19 Y 24
Així que tenim:
1 2 3 4 5 6 7 8 25
A aquests números se'ls ha d'aplicar el pes 7-3-1
. Això significa
que s'han de multiplicar per 7
, per 3
o per 1
depenent de la
seva posició:
1 2 3 4 5 6 7 8 25
7 3 1 7 3 1 7 3 1
--------------------------
7 6 3 28 15 6 49 24 25
A continuació s'han de sumar els resultats de totes les multiplicacions:
7 + 6 + 3 + 28 + 15 + 6 + 49 + 24 + 25 = 163
El dígit de control és el darrer dígit del resultat de la suma, 3
en
aquest cas.
Implementació de l'algorisme
Aquí s'inclou una implementació de l'algorisme escrita en el llenguatge de programació C.
La funció check_digit
definida a continuació rep un paràmetre de
tipus char *
que ha d'apuntar a una cadena que conté dígits i/o
lletres. Retorna un int
entre 0
i 9
que és el dígit de control
de la cadena. En cas de trobar un caràcter no vàlid, retorna -1
.
#include <ctype.h>
int
check_digit(char *s)
{
static int m[3] = { 7, 3, 1 };
int i, n;
for (i = n = 0; s[i] != '\0'; i++)
if (isdigit(s[i]))
n += (s[i] - '0') * m[i % 3];
else if (isalpha(s[i]))
n += (toupper(s[i]) - 'A') * m[i % 3];
else
return -1;
return n % 10;
}
Prova de concepte
Si tens un DNI electrònic, omple els següents camps amb el número de sèrie del suport físic del teu DNI, el teu número de DNI, la teva data de naixement i la data de caducitat del teu DNI tal com apareixen al revers del teu DNI. Els dígits de control s'ompliran automàticament.
En canvi, si tens un DNI tradicional, omple els següents camps amb el teu número de DNI, la teva data de naixement i la data de caducitat del teu DNI tal com apareixen a darrere del teu DNI.
La pròxima vegada que escoltis la llegenda urbana de que el número del revers del DNI indica el número de persones que tenen el mateix nom i cognoms que tu, explica'ls que no és així!
Història
A l'any 2005, cansat d'escoltar el mite dels números del DNI, vaig decidir cercar la solució a l'enigma: ¿si no és el número de persones amb el teu nom i cognoms, què és llavors?
Abans de saber res sobre l'origen dels dígits de control o saber amb certesa si realment ho eren, ja pensava que no era provable que aquell dígit fos el que deien. No semblava pràctic introduir una dada que depèn de tants factors externs al portador del document, ja que podria tornar-se obsoleta amb facilitat i no tindria cap valor. Si de veritat necessitessin saber aquesta dada, l'ideal seria consultar-ho a una base de dades.
Vaig llegir sobre la possibilitat de que fossin dígits de control a un weblog i em va sembla raonable. El que semblava més segur era que el dígit que seguia a la data de naixement i a la de caducitat es calculava a partir de la data, i la meva investigació es va basar en això.
Gràcies als meus amics, vaig arreplegar unes quantes mostres per comparar. Vaig intentar aplicar diversos algorismes comuns per obtenir dígits de control, però no vaig tenir èxit.
Un dia vaig poder comparar dues dates que es diferenciaven només en el
segon dígit. Suposant que l'algorisme funcionava amb un sistema de
pesos (números amb els quals s'han de multiplicar els valors segons
les seves posicions), una suma i l'extracció del darrer dígit, vaig
deduir que el pes de la segona posició era un 3
.
Vaig decidir afrontar el problema mitjançant força bruta, ja que
semblava possible. Només hi havia 10 valors diferents i 6 posicions,
així que vaig fer un script que aplicava totes les combinacions de
pesos possibles i comprovava el resultat amb totes les mostres que
tenia. Va sortir bé i vaig obtenir els pesos, 7-3-1
.
Així que ja sabia com obtenir el dígit de control de les dates, però
hi havia un problema per aplicar-lo al dígit que seguia el número del
DNI a la primera línia. Aquest número contenia una lletra, i per
tant, vaig tenir que descobrir com s'obtenia el seu valor numèric.
Després de poques proves vaig aconseguir la resposta: A=0
,
B=1
… Z=25
.
Només faltava el darrer dígit, el que em va motivar a començar aquesta investigació. El problema era que en estar separat de les altres dades el seu origen no era obvi.
Vaig estar un temps fent proves i no arribava a un resultat exacte.
Finalment vaig llegir una referència a cert document,
9303 de la ICAO, que suposadament explicava tot això.
No vaig poder tenir accés a aquest document, ja que llavors no estava
disponible online, però vaig trobar documents
explicant el sistema de pesos 7-3-1
i la seva aplicació a
passaports, citant com a font el document 9303. Però les dades OCR
del passaport tenen un format diferent al del DNI, així que no vaig
trobar la solució, però vaig aconseguir una pista: el darrer dígit de
control de les dades OCR d'un passaport es calcula de la mateixa
manera que els altres dígits de control explicats en aquest document,
però el seu origen és una selecció de les dades anteriors; vaig llegir
que el sexe i la nacionalitat no es veien reflectits a aquest dígit de
control, i llavors em vaig adonar de per què encara no havia trobat la
resposta: en totes les proves que havia fet sempre incloïa el caràcter
del sexe. Així que en provar només amb els dígits de control i els
seus camps associats vaig aconseguir coincidència a totes les mostres.
Sis anys després encara no disposava de DNI electrònic, però vaig poder analitzar unes mostres que em van deixar amablement. Comparant un DNI electrònic amb un DNI tradicional vaig veure que la primera línia de les dades OCR havia canviat de format; hi havia alguna cosa més abans del número del DNI, que vaig identificar com el número de sèrie que apareix a la part davantera i el seu dígit de control; a més el número de DNI ja no tenia dígit de control darrere. Seguidament vaig fer un parell de proves i vaig trobar la nova forma de calcular el dígit de control.