Voici la description d'un programme que j'ai développé pour en savoir plus sur la question du code indéchiffrable. Comme il arrive très souvent au oeuvres de jeunesse des programmeurs, les sources de cette étude sont aujourd'hui enfermées dans un environnement défunt tournant sur une machine que je n'ai plus. On ne peut pas passer sa vie à tout reprogrammer et je me contente maintenant d'une esquisse sommaire. Ce genre de programme n'est après tout qu'un exercice de style !
Il existe beaucoup de formules pour fabriquer une liste de nombres compris entre 0 et 1 et dont la succession dessine un motif qui semble n'avoir aucun sens. On ne serait pas surpris d'entendre dire que ces nombres sont aléatoires. Ils ne le sont pas. La caractéristique première de ces formules est qu'elles sont parfaitement prévisibles. La fonction est simple :
x1 <- f(x0)
x2 <- f(x1)
x3 <- f(x2)
etc.
Une même valeur pour la "graine" x0 génère toujours la même série de nombres. Le principal défaut de ces formules est de reproduire une valeur déjà rencontrée au bout un certain nombre d'itérations. A partir de ce point, on reproduit naturellement en boucle toute la série de nombres située entre les deux premières occurences de la valeur ainsi régénérée, ce qui n'a plus rien d'aléatoire. Ces formules sont donc plus robustes quand la boucle devient plus longue. Mais la longueur de la série dépend aussi de la graine x0 choisie.
Pour nos besoins ici, la nature exacte du générateur importe peu. Il n'est pas indispensable que la formule soit courte et élégante. Considérons que l'on dispose d'un générateur suffisamment robuste pour toutes les graines possibles et qui donne ainsi l'illusion de hasard pour une série de quelques centaines ou milliers de nombres. La graine est essentiellement la "clef" pour les applications cryptographiques. La liste qui en découle semblera aléatoire pour qui ne possède pas cette clef.
Considérons pour les besoins de l'illustration que le message suivant doit rester secret :
Pour chacun des caractères de ce message à tour de rôle, on fabrique une nouvelle roue cryptographique avec le générateur de nombres aléatoires. Elle sert directement et simplement dans la fonction de remplacement des signes :
c1 <- r(x1,s1)
c2 <- r(x2,s2)
c2 <- r(x3,s3)
etc.
En supposant qu'on utilise un jeu d'une centaine de caractères dans une roue cryptographique et en sachant qu'il faut 32 roues pour 32 signes à substituer, il faut ici une série de 100 x 32 nombres pseudo-aléatoires pour transformer le message en signes déroutants :
Cette procédure rend parfaitement vain l'espoir de décoder selon la fréquence des caractères en français puisque le même caractère en clair peut être représenté par des caractères cryptés différents et inversement. Il ne faut que quelques secondes à un ordinateur actuel pour obtenir ce résultat.
Dans un scénario de décodage classique, une fois écartée la possibilité de détecter une régularité significative, on envisage l'attaque par une méthode dite de force brute. En l'occurence, il faudrait que celui qui possède la procédure et intercepte le message crypté - mais pas la clef ! - examine toutes les clefs possibles jusqu'à ce que le message se dévoile. En supposant que que l'on utilise une clef de huit chiffres, il suffit d'examiner (détecter la présence de mots ayant un sens par un moyen informatique quelconque) les résultats de cent millions de clefs. Il faudrait sans doute quelques jours ou semaines à l'ordinateur, sans compter le temps de développement, pour réussir l'attaque. Et l'attaque réussit !
Pour fermer définitivement cette porte ouverte à l'attaque, il suffit en principe d'augmenter le nombre de chiffres de la clef. Un moyen des plus simples pour effectuer cette amélioration consiste à re-crypter plusieurs fois le message en changeant de clef à chaque fois et en prenant chaque fois le dernier message crypté en guise de message en clair. Voici une présentation possible de l'itération de la procédure :
itération | clef | message |
0 | - | il fait beau et le ciel est bleu |
1 | 82562499 | fb(0d.(g.,.w:ev+m-lw9@>g&+[lrd%i |
2 | 25754003 | 7bp535<p)i8w>li1m)qw(q 'j@w'3,29 |
3 | 32016631 | uy w6m?9<+ica%=1kv%4;;%78rhg8n@o |
4 | 32143564 | vup7#$l/t&.9;1).7z+s66rtnza,1m@s |
5 | 42669790 | sk!lgj3w4[%9wt.d+1w;7m7$)qy87w?7 |
6 | 32176139 | atc+;wuj>o!qhe1#f'i*0k8gv#mofr&= |
7 | 17121309 | ju: &;?@&mv5y836obfff7ns7yp(u/j4 |
8 | 83753066 | +%$0;36#,2<*&,md*$=w:b;*<ya?dw;4 |
9 | 69623336 | j"bze'wd'z$'d<6(7gplx<(/:jqc7iy6 |
10 | 56407136 | ;3@,fi4f1/n>yo?j"z7m%1m9ip2",8sd |
11 | 09813227 | /[air<jy< 2* *f+r*97<$xrat&p&vl1 |
12 | 98829462 | $qk$;3jvp[-yp80[!:9($g[/6q@%v4,> |
13 | 93873772 | >k%0-l>s0n!t)$(/*id7(2-n8">1re5h |
14 | 15664028 | f'i!ajne0m#ca'*?f.9#a4[pos($g?94 |
15 | 23322125 | q/-)x3393*ria%[g,.lf5ef8)pdn+l'# |
Le but des cryptages successifs n'est pas de rendre le message incompréhensible (il l'est déjà) mais seulement de garantir la robustesse du code. Il faut conserver toutes les clefs et le dernier message crypté. Le codage ou le décodage ne réclame que quelques minutes à un ordinateur de bureau actuel. Une série de clefs composée de quinze nombres de huit chiffres réclamerait à l'attaquant un nombre d'essais de l'ordre de 10^100. L'attaque par la force brute réclamerait plus de temps qu'il ne s'en est écoulé depuis le big bang à plus de machines qu'il n'y a d'atomes dans l'univers. L'attaque échoue !
Le problème du code parfaitement impénétrable par la force est résolu par la force.
Au lieu de spéculer sur la fin prochaine de l'art du décryptage, je préfère commencer par démontrer une fois pour toutes l'existence de codes indéchiffrables. Le dicton selon lequel "ce qu'un homme peut faire, un autre peut le défaire" s'avère inexact. Contrairement à ce qu'on laisse quelquefois entendre dans la presse, la définition du code incassable ne réclame pas d'autres mathématiques que l'algèbre que possède n'importe-quel collégien de quatorze ans.
Dès lors, l'activité du bidouilleur qui "débride" les logiciels au lieu de les acheter n'a aucune valeur. Si le débridage est possible, ce n'est que parce que le créateur du programme le veut bien. Quiconque se vante d'avoir "cassé une protection" n'impressionne que lui-même. Autant se vanter d'avoir "volé" un échantillon gratuit dans un supermarché. Débrider réclame sans doute un talent que je n'ai pas mais, si j'ai un conseil à donner à un jeune programmeur, c'est de ne pas perdre son temps avec un jeu aussi stupide. C'est un mauvais investissement. Le programmeur qui désire ainsi prouver ses capacités ne mérite que le mépris de la communauté. C'est aujourd'hui un lieu commun : casser pour casser est moins que jamais un but légitime.
Quant à la fabrication des codes secrets et des autres systèmes de protection de l'information, je viens aussi d'en révéler l'essence dérisoire. C'est une activité qui ne devrait pas retenir longtemps l'intérêt du programmeur soucieux de l'utilité de son travail. J'avoue pour ma part avoir toujours un faible pour les applications ludiques de la cryptographie.