Josep Portella

Desmitificant els números del DNI

Setembre de 2005
Actualitzat: juliol i agost de 2011
Traduït: març de 2012

© 2012 Josep Portella Florit
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<<<<<<]
  1. Tipus de document
  2. Nació
  3. Número de sèrie del suport físic de la targeta
  4. Dígit de control del camp 3
  5. Número de DNI
  6. Farciment
  7. Data de naixement (AAMMDD)
  8. Dígit de control del camp 7
  9. Sexe (M/F)
  10. Data de caducitat
  11. Dígit de control del camp 10
  12. Nacionalitat
  13. Farciment
  14. Dígit de control dels camps 3, 4, 5, 7, 8, 10 i 11 concatenats
  15. 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<<<<<<]
  1. Tipus de document
  2. Nació
  3. Número de DNI
  4. Dígit de control del campo 3
  5. Farciment
  6. Data de naixement (AAMMDD)
  7. Dígit de control del camp 6
  8. Sexe (M/F)
  9. Data de caducitat
  10. Dígit de control del camp 9
  11. Nacionalitat
  12. Farciment
  13. Dígit de control dels camps 3, 4, 6, 7, 9 i 10 concatenats
  14. 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.

IDESP <<<<<<
 ? ???<<<<<<<<<<< 

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.

IDESP <<<<<<<<<<<<<<<
 ? ???<<<<<<<<<<< 

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=1Z=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.