Tuesday, January 02, 2018

Cartes d'identité et passeports suisses

Une rumeur circule parmi les enfants des écoles en Suisse. Elle dit que le chiffre à la fin du numéro de la carte d'identité indique le nombre de sosies. Et celà serait utile pour les caméras de surveillance et leurs logiciels de reconnaissance faciale.

C'est évidemment absurde, mais le phénomène est tout de même intéressant d'un point de vue sociologique et politique, puisqu'il reflète une perception plutôt inquiétante de nos sociétés par les enfants. Après tout, les logiciels de reconnaissance et les caméras de surveillance sont bien réels...

Cependant, la sociologie et la psychologie enfantine étant des domaines bien trop complexes pour moi, j'ai juste voulu savoir ce qu'étaient réellement ces chiffres. Sûrement des chiffres de contrôle, qui apparaissent à la fin de tous les codes qui doivent pouvoir être lus par des machines, comme le nos des comptes bancaires, des cartes de crédit, etc.

La signification des chiffres est vaguement expliquée sur le site de la Confédération pour les passeports, mais pas pour les cartes d'identité. Quand à l'agorithme utilisé pour le calcul du chiffre de contrôle, il n'est mentionné nulle part. De plus, sur l'exemple qui illustre les chiffres pour le passeport, le chiffre de contrôle est FAUX!

L'exemple indique "9" en bas à droite au lieu de "6"!

Avec une telle avarice d'explications de la part des autorités, il n'est pas étonnant de voir surgir des rumeurs bizarres.

Heureusement, pour la carte d'identité, il y a une page en allemand de Wikipedia qui explique le tout, y compris l'algorithme utilisé pour les chiffres de contrôle.

Ainsi, après mon exploration ancienne du calcul "modulo 10" pour certains chiffres de contrôle de banques et autres, j'ai pu m'amuser à faire un petit script qui donne le nombre de sosies les chiffres de contrôle pour les cartes d'identité et les passeports suisses.
L'algorithme de base en Perl est dans cette fonction "cksum":

sub cksum {
 my $num = shift;
 $num = uc( $num );       # convert tu uppercase
 $num =~ s/[^A-Z0-9<]//g; # and remove spaces etc.

 my @digits = split //, $num;
 my @multipliers = (7,3,1);
 my $cksum = 0;

 for (my $i=0; $i < @digits; $i++) {
  my $n = $digits[$i];

  $n = 0 if ($n eq "<");

  if ($n =~ /[A-Z]/) {  # A=>10, B=>11, ..., Z=>35
   $n = ord( $n ) - 55;
  }

  $cksum += $n * $multipliers[ $i % 3 ];
 }
 return $cksum % 10; # keep only last digit
}

Et pour les geeks, le script complet est ici.

Labels: , ,