Mémoire sur Enigma
Transcription
Mémoire sur Enigma
Enigma Chebitchov 5 avril 2009 Table des matières 1 Introduction 2 2 Historique 2 3 Fonctionnement 3 4 Modélisation d'une machine Enigma en Python 5 5 Conclusion 9 3.1 3.2 4.1 4.2 Théorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mécanisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modélisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 5 5 7 A Bibliographie 10 B Diagramme de classes 10 B.1 Rotor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.2 Reecteur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.3 Enigma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C Codes C.1 C.2 C.3 C.4 rotor.py . . reecteur.py enigma.py . test.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 10 10 10 10 12 12 14 1 Introduction Enigma marque, dans l'histoire de la cryptographie, le passage de la cryptographie manuelle à la cryptographie mécanisée puis informatisée. Pour la première fois, une machine a été utilisée pour crypter des communications, et une autre machine a été utilisée pour casser le code de ces communications. Après un bref rappel historique, j'expliquerai le fonctionnement de la machine d'un point ded vue théorique puis d'un point de vue mécanique. Enn, je présenterai un programme écrit en Python reproduisant le fonctionnement d'Enigma 2 Historique L'histoire d'Enigma commence à la n de la première guerre mondiale. C'est en eet à cette époque qu'Arthur Scherbius, un industriel allemand, dépose un premier brevet concernant une machine à chirer. Par la suite, il rachète un deuxième brevet similaire d'un inventeur hollandais, Hugo Koch, et c'est sur la base de ces deux machines qu'est développée Enigma, qui est commercialisée pour la première fois sous le nom d'Enigma A en 1923. L'armée allemande commence à s'intéresser à Engima à partir de 1926. C'est à cette époque que la marine allemande adopte Enigma D, qu'elle perfectionne, pour crypter ses communications. La machine devient alors petit à petit le moyen de cryptage des communications de l'armée allemande puis de l'Axe. Elle est notamment utilisé durant la guerre d'Espagne. Parallèlement, les autres pays essaient de casser Enigma. Ce sont des mathématiciens Polonais (Marian Rejewski, Jerzy Ró»ycki et Henryk Zygalski) qui arrivent à casser la machine en 1933. Ils se sont aidés pour cela de machine électromécanique, les bombes cryptographiques. Cela permettra à la Pologne de connaitre la date de l'attaque de l'Allemagne en septembre 1939. Néanmoins, suite à cette attaque et à un nouveau perfectionnement de la machine, les Polonais sont dépassés et décident d'envoyer leurs résultats à la France et à l'Angleterre. L'Angleterre installe alors à Bletchley Park, à quelques encablures de Londre, une communauté de scientiques, joueurs d'échecs, cruciverbistes... dans le seul but de casser les codes allemands et de déchirer les communications. Un homme notamment jouera un grand rôle dans ce travail, Alan Turing. S'appuyant sur les erreurs des opérateurs allemands (envoi de message de test composée d'une seule lettre, envoi de messages commençant toujours de la même manière) et sur l'un des tous premiers ordinateurs, Colossus, ce grand mathématicien parviendra dès 1942 à casser les codes d'Enigma et à déchirer les messages en moins d'une journée. Il arrivait que les instances alliés soient au courant du contenu des messages avant l'état-major Allemand. 2 Après la n de la guerre, on estimera que, sans le décryptage d'Enigma, la guerre aurait durée 2 ans de plus. 3 Fonctionnement 3.1 Théorie Le cryptage par la machine Enigma se base sur plusieurs permutations d'une part, et sur une permutation circulaire de ces permutations. Voir le tableau cidessous pour un exemple de permutation A F B E C Z D K ... ... Y P Z U Le principe de la machine Engima est de multiplier ce type de permutation. Ainsi, sur les machines militaires de première génération, il y avait une suite de trois permutations de ce type. Une fois les trois permutation eectué, on avait à faire à une permutation spéciale, appelée réecteur, qui permutait les lettres deux à deux. Une fois cette permutation faites, on réeectuait les permutations dans l'autre sens. Ainsi, le codage d'une lettre par une Enigma de première version militaire peut se traduire ainsi en expression mathématique : C = M P1 P2 P3 RP3−1 P2−1 P1−1 Où M est la lettre à coder, C la lettre codée, P1 , P2 , P3 sont les trois permutations de base et R le réecteur. On constate facilement que pour décoder un code d'Enigma, il sut d'executer la même opération, ce qui se traduit par la formule ci-dessus. En eet R étant une permutation 2 à 2, on a R−1 = R : M = CP1 P2 P3 RP3−1 P2−1 P1−1 Tout ceci étant pour le codage d'une lettre. En eet, si on s'en tenait là pour le codage d'un message entier, chaque lettre serait toujours codé par la même lettre et donc une simple analyse statistique permettrait de decrypter le message. Pour éviter cela, Enigma, à chaque lettre, tourner les permutations. Ainsi, en reprenant la permutation du premier tableau, cela deviendrait après une première rotation : A V B G C F D A 3 ... ... Y J Z Q On constate que cette rotation a lieu sur les relations entre les lettres et non pas sur le tableau de lettre. Ainsi, dans le premier tableau, B est codé par E, il y a donc un décalage de trois lettres. Donc à la rotation suivante, C sera codé par F (C + décalage de 3 lettres) et non pas par E. Cela pour une seule permutation. Dans un cas d'utilisation réel, la première permutation tournait à chaque lettre tapée. Pour le deuxième, toutes les 26 lettres et pour le troisième toutes les 676 lettres. ainsi, pour un message de n lettre, le codage peut mathématiquement s'écrire ainsi : C = M (ρi P1 ρ−i )(ρj P2 ρ−j )(ρk P3 ρ−k )R(ρk P3−1 ρ−k )(ρj P2−1 ρ−j )(ρi P1−1 ρ−i ) Avec : ρ la permutation circulaire, i le numero de la lettre dans le message modulo 26, j la partie entière du numero de la lettre divisé par 26 modulo 26, k la partie entière du numero de la lettre divisé par 676 modulo 26, P , M , R et C restant les mêmes que pour la première équation Nombre de clés possibles et sureté du système Enigma n'a pas de clé à proprement parler, la sureté de son cryptage repose sur le choix de l'ordre des permutations P1 , P2 , P3 et sur la position d'initialisation de ces trois permutations (iinitial , jinitial , kinitial ). Sur une machine Enigma de base, il existait également une permière permutation par groupe de 6 lettres que je n'ai pas représenté, et qui était modiables par les opérateurs. Ce qui nous donne, pour l'Enigma que j'ai modélisée, une clé composée de 9 chires. Les trois premiers étant la position des permutations (123, 312, ...), les 6 suivants étant les position d'initialisation de i, j, k (020424, 230712, ...) Donc, si on récapitule les diérentes protections, on arrive au décompte suivant : la façon d'ordonner 3 éléments (les trois permutations) : 6 la façon d'initialiser les 3 permutations : 26 · 26 · 26 = 17576 On arrive donc à un total de 6 · 17576 = 105456. Si l'on ajoute la première permutation que je n'ai pas prise en compte, on arrivait à 100391791500 · 105456 soit plus de 1 · 1016 possibilités On remarquera que je prends pas en compte les permutations comme moyen de complexier le système. En eet, la machine Enigma étant mécanique, il était facile de connaitre les permutations qui n'était pas modiables facilement (une fois qu'on avait une machine Enigma, on avait les permutations). 4 Système cryptographique complet : On peut donc desormais donner le 5-uplet qui décrit le système cryptographique: P : tous les messages possibles, privé de tous ses caractères spéciaux (espace, accents...) C : toutes les combinaisons de lettres possibles K : dans mon cas, l'ordre des trois permutations et les initialisations de ces permutations (a, b, c , iinitial , jinitial , kinitial ) ek : (ρi+iinitial Pa ρ−i−iinitial )(ρj+jinitial Pb ρ−j−jinitial )(ρk+kinitial Pc ρ−k−kinitial ) R(ρk+kinitial Pc−1 ρ−k−kinitial )(ρj+jinitial Pb−1 ρ−j−jinitial )(ρi+iinitial Pa−1 ρ−i−iinitial ) dk : ek 3.2 Mécanisme La machine Enigma est une machine électromécanique. C'est à dire qu'elle s'appuie à la fois sur des courants électriques et des mécanismes. Ainsi, les permutations était des liaisons électriques imprimé sur des rotors. Eectuer la permutation circulaire consistait donc à faire tourner le rotor d'un cran. On voit aussi bien pourquoi les permutations ne pouvaient être considéré comme une protection, les rotors devant être acheminé vers les machines, ce qui, dans le cadre d'un parc de plusieurs milliers de machines, augmentaient les risques de vol ou d'interception de la part de l'ennemis. Pour la première permutation (celle que je n'ai pas traitée), elle se faisait à l'aide de ls que les opérateurs branchaient de diérentes manières selon le jour. De manière plus générale, chaque opérateur avait un livre de codes permettant de savoir comment brancher sa machine Enigma selon la date du jour, et ainsi comment coder les transmissions. Cela explique aussi pourquoi il était d'une importance vitale pour les alliés de se procurer ces livres, d'où l'histoire de la capture du sous-marin U-110 et de sa machine Enigma en 1941. 4 Modélisation d'une machine Enigma en Python 4.1 Modélisation Pour modéliser une machine enigma, j'ai d'abord crée deux classes. L'une, la classe rotor, devant modéliser un rotor et les opérations habituelle sur celuici (création, initialisation, rotation). L'autre, la classe réecteur, modélisant le réecteur. J'ai ensuite modélisé une machine Enigma comme une suite de rotors et un réecteur, et pouvant eectuer diverses opérations (crypter, s'initialiser). le rotor : Le rotor possède deux attributs. D'abord un tableau permutation où le numéro de l'index correspond à l'entré et la valeur stockée à l'index correspond 5 à la sortie. Et un tableau départ, qui est équivalent à un tableau permutation mais qui lui ne bouge pas lors d'une rotation, ce qui permet de conserver l'état de départ du rotor. Init : permet d'initialiser le rotor. Pour cela on crée un tableau indenté de 0 à 25. Après, on prend aléatoirement une valeur dans ce tableau, on la supprime du tableau indenté et on l'ajoute au tableau permutation. En eectuant cette opération 26 fois, notre tableau permutation est rempli de valeurs allant de 0 à 25 ordonnée aléatoirement. rotation : faire tourner le tableau des permutations d'un cran. Pour cela, dans un premier temps, on prends le dernier élement du tableau permutation que l'on envoie au début de permutation. Après on ajoute 1 à chaque élément de permutation (modulo 26) pour prendre en compte le fait que dans une machine Enigma, ce sont les relations entre les lettres qui tournent et non pas les lettres. initialisation : permet d'initialiser le rotor à une position n donnée en argument. Cela consiste à faire tourner n fois le rotor à l'aide de la méthode rotation, puis d'envoyer le tableau permutation dans le tableau depart an de conserver la position de départ. réinitialisation : permet de revenir à la position initialisée du rotor. Cela consiste à copier le tableau depart dans le tableau permutation. Le réecteur : Le reecteur possède qu'un attribut, le tableau permutation semblable à celui du rotor. Mais comme le reecteur est en fait une permutation particulière (permutation 2 à 2), l'initialisation va être diérente. On n'a pas besoin de tableau depart car le réecteur ne tourne pas. Init : on reprend le meme principe que pour l'Init d'un rotor. On crée donc un tableau indenté de 0 à 25. On remplie également le tableau permutation de 0. Après, on pioche 2 éléments a et b aléatoirement à la suite dans le tableau indenté, on les supprime du tableau indenté et on met dans le tableau des permutations a à l'index b et b à l'index a. La machine Enigma : La machine Enigma a comme attribut un réecteur et un tableau de n rotors, n étant choisi lors de la création de la machine Init : Pour l'initialisation, on a n comme paramètre, n étant le nombre de rotors que l'on veut dans notre machine. On crée donc un réecteur et n rotors que l'on met dans un tableau. 6 cryptage : Enn la méthode intéressante. Cette méthode prend en argument une chaine de caractères. Pour chaque caractère, on le convertit d'abord en nombre de 0 à 25 (on remarquera alors que le programme plante lorsqu'on utilise autre chose que des lettres minuscules). Nous avons alors un nombre k . Pour le premier set de permutations (celui avant le reecteur, reecteur inclu), cela consiste à mettre dans k la k ime valeur du tableau des permutations du rotor/réecteur traité. Pour le deuxième set (les permutations inverses), on met dans k l'index où est situé la valeur k dans le tableau des permutations du rotor traité. Enn on reconverti le nombre obtenu en lettre que l'on ajoute à une chaine de caractères résultat. Enn, on fait tourner les rotors, le premier tournant tout le temps, le deuxième une fois toutes les 26 lettres et ainsi de suite. À la n de la fonction on retourne la chaine résultat. initialisation : Cette méthode, qui prend en argument un tableau d'entier allant de 0 à 25 et de la taille du nombre de ressorts dans la machine (on constatera que cela n'est pas testé, d'où des erreurs en cas de passage d'un argument non valide), consiste à initialiser chaque rotor du tableau des rotors à la valeur contenue dans le tableau passé en argument. réinitialisation : Pour chaque rotor du tableau de rotors, on réinitialise le rotor. 4.2 Tests Nos tests ont tous été eectués avec une machine enigma à 3 rotors. Ces tests ont consisté à coder une chaine de caractère de taille 27 contenant qu'une seule lettre, ici la lettre v Caractéristiques du test : rotor 1 : [11, 22, 16, 6, 23, 18, 17, 25, 1, 24, 3, 15, 14, 2, 10, 19, 12, 21, 9, 20, 8, 7, 4, 13, 5, 0] rotor 2 : [19, 25, 11, 15, 13, 6, 20, 7, 2, 4, 8, 5, 1, 0, 3, 14, 22, 9, 16, 23, 10, 24, 18, 12, 17, 21] rotor 3 : [4, 9, 25, 23, 2, 15, 14, 10, 22, 18, 16, 8, 19, 20, 17, 24, 3, 7, 0, 6, 21, 1, 13, 12, 5, 11] réecteur : [7, 20, 21, 12, 25, 24, 22, 0, 15, 19, 11, 10, 3, 17, 16, 8, 14, 13, 23, 9, 1, 2, 6, 18, 5, 4] résultats : chaine non codée : vvvvvvvvvvvvvvvvvvvvvvvvvvv chaine codée : izdwdxpcntdoyjhiuqoqlhjjuaj chaine décodée : vvvvvvvvvvvvvvvvvvvvvvvvvvv 7 On peut déjà remarquer que la chaine est codée et décodée. Nous allons regarder maintenant plus en détail ces résultats. Test 1 : codage d'une lettre. Nous nous intéressons à la première lettre : codons-là manuellement. Voici la chaine que cela suit dans le tableau suivant : lettre v conversion 21 P1 7 P2 7 P3 10 R 11 P3−1 25 P2−1 1 P1−1 8 conversion i On constate que la première lettre, dans les résultats, est bien codée par un i. Le premier test est positif. Test 2 : codage de deux lettres. Dans ce test, nous vérions la rotation du premier rotor en codant la lettre suivante. Voici la chaine que cela suit dans le tableau suivant : lettre v conversion 21 P1 9 P2 4 P3 2 R 21 P3−1 20 P2−1 6 P1−1 25 conversion z La deuxième lettre est bien codée par un z , le résultat est positif. Test 3 : codage de la 27ième lettre. Dans ce test, nous vérions la rotation du deuxième rotor en codant la 27ième lettre. Voici la chaine que cela suit dans le tableau suivant : lettre v conversion 21 P1 7 P2 21 P3 1 R 20 P3−1 13 P2−1 24 P1−1 9 conversion j La deuxième lettre est bien codée par un j , le résultat est positif. Remarques : dans le premier et le troisième test, après le passage dans le premier rotor, la lettre v est codée par le même nombre 7. C'est normal car après 26 tours, le premier rotor est revenu à sa position initiale. La lettre v n'est jamais codée par elle même. C'était aussi vrai pour la machine Enigma réelle, ce qui permettait de casser son code encore plus facilement. 8 5 Conclusion Modéliser une machine Enigma est nalement assez simple et permet de bien comprendre le fonctionnement de ladite machine (faiblesses...). Néanmoins, il manque encore pas mal de choses à mon programme (ajout de la première permutation, possibilité de charger une machine avec des rotors déjà fait...). Sinon, je n'ai pas eu trop le temps d'aborder la cryptanalyse de la machine Enigma, ce qui pourrait être également intéressant (comment retrouver le code en connaissant les rotors). 9 A Bibliographie http://fr.wikipedia.org/wiki/Enigma_(machine) http://fr.wikipedia.org/wiki/Cryptanalyse_d%27Enigma http://www.bibmath.net/crypto/debvingt/enigmafonc.php3 B Diagramme de classes B.1 Rotor rotor +permutation : int[26] +depart : int[26] +rotor() +rotation() +initialisation(n : int) +reinitialisation() B.2 Reecteur reecteur +permutation : int[26] +reecteur() B.3 Enigma enigma +rotors : rotor[] +reecteur : reecteur +enigma(n : int) +cryptage(texte : string) +initialisation(tab : int[]) +reinitialisation() C Codes C.1 rotor.py import class random rotor ( object ) : #classe implementant un rotor d 'une machine enigma def __init__ ( s e l f ) : #Creation d 'un rotor 10 s e l f . permutation = [ ] s e l f . depart = [ ] tableau = [ ] #creation d 'un tableau i n i t i a l i s e de 0 a 25 for i in r a n g e ( 2 6 ) : t a b l e a u . append ( i ) #creation v e r i t a b l e du rotor i = 0 while ( i <26) : a = t a b l e a u . pop ( random . r a n d i n t (0 ,25 − i ) ) s e l f . p e r m u t a t i o n . append ( a ) s e l f . d e p a r t . append ( a ) i = i + 1 def rotation ( s e l f ) : #methode permetant de f a i r e tourner le rotor s e l f . p e r m u t a t i o n . i n s e r t ( 0 , s e l f . p e r m u t a t i o n . pop ( − 1) ) s e l f . p e r m u t a t i o n = map( a j o u t e , s e l f . p e r m u t a t i o n ) def initialisation ( self , a) : #methode permettant d ' i n i t i a l i s e r le rotor a l ' entier a for for def reinitialisation ( self ) : #remise du rotor a l ' etat i n i t i a l for def i in r a n g e ( a ) : s e l f . rotation () i in r a n g e ( 2 6 ) : s e l f . depart [ i ] = s e l f . permutation [ i ] i in r a n g e ( 2 6 ) : s e l f . permutation [ i ] = s e l f . depart [ i ] ajoute (x) : #fonction permettant d ' ajouter 1 modulo 26 ( u t i l i s a t i o n dans la methode rotation ) return ( x + 1 ) % 26 11 C.2 reecteur.py import class random reflecteur ( object ) : #classe implementant le reflecteur , qui est un rotor particulier def __init__ ( s e l f ) : #i n i t i a l i s a t i o n a partir de rien s e l f . permutation = [ ] tableau1 = [ ] #creation d 'un tableau i n i t i a l i s e de 0 a 25 for i in r a n g e ( 2 6 ) : t a b l e a u 1 . append ( i ) s e l f . p e r m u t a t i o n . append ( 0 ) #creation de la permutation i = 26 while i >0: a = t a b l e a u 1 . pop ( random . r a n d i n t ( 0 , i − 1) ) b = t a b l e a u 1 . pop ( random . r a n d i n t ( 0 , i − 2) ) i = i − 2 s e l f . permutation [ a ] = b s e l f . permutation [ b ] = a #on remarquera que cette methode permet d ' e v i t e r que a et b valent la meme chose C.3 enigma.py from from r e f l e c t e u r import * r o t o r import * class enigma ( o b j e c t ) : #classe modelisant une machine enigma s i m p l i f i e e def __init__ ( s e l f , t a i l l e ) : #i n i t i a l i s a t i o n de la machine s e l f . rotors = [ ] s e l f . reflecteur = reflecteur () for i in r a n g e ( t a i l l e ) : s e l f . r o t o r s . append ( r o t o r ( ) ) def cryptage ( s e l f , texte ) : 12 #fonction de cryptage et de decryptage d 'un message resultat = ' ' i = 0 while i <( l e n ( t e x t e ) ) : #on convertie en nombre de 0 a 25 v a l e u r = ord ( t e x t e [ i ] ) −97 #encore une fois , on ne v e r i f i e pas si on a a f f a i r e a des caractere de l e t t r e minuscule # passage dans le premier set de rotor for j in r a n g e ( l e n ( s e l f . r o t o r s ) ) : valeur = s e l f . r o t o r s [ j ] . permutation [ valeur ] # passage dans le r e f l e c t e u r valeur = s e l f . r e f l e c t e u r . permutation [ valeur ] # passage dans l e s rotors dans l ' autre sens for j in r a n g e ( l e n ( s e l f . r o t o r s ) ) : v a l e u r = s e l f . r o t o r s [ l e n ( s e l f . r o t o r s )− j −1]. permutation . index ( valeur ) # on envoie le tout dans l e s r e s u l t a t s r e s u l t a t = r e s u l t a t + ( c h r ( v a l e u r +97) ) # on incremente i = i + 1 # et on gere la rotation des rotors for j if in range ( len ( s e l f . r o t o r s ) ) : ( j ==0) or ( i % ( 2 6 * j ) == 0 ) : s e l f . rotors [ j ] . rotation () # on revoie le r e s u l t a t return def i n i t i a l i s a t i o n ( s e l f , tab ) : #fonction i n i t i a l i s a n t la position de depart des rotors for def resultat j in r a n g e ( l e n ( s e l f . r o t o r s ) ) : s e l f . r o t o r s [ j ] . i n i t i a l i s a t i o n ( tab [ j ] ) reinitialisation ( self ) : #r e i n i t i a l i s e a la position de depart des rotors for j in r a n g e ( l e n ( s e l f . r o t o r s ) ) : s e l f . rotors [ j ] . r e i n i t i a l i s a t i o n () 13 C.4 test.py from enigma import * # creation et i n i t i a l i s t a t i o n de la machine machine = enigma ( 3 ) machine . i n i t i a l i s a t i o n ( [ 1 , 2 , 3 ] ) # affichage des c a r a c t e r i s t i q u e s de la machine print ( " v o i c i comment for i in r a n g e ( 3 ) : print ( " r o t o r " + e s t i n i t i a l i s e e n o t r e enigma : " ) s t r ( i +1) + " : " + s t r ( machine . r o t o r s [ i ] . permutation ) ) print ( " r e f l e c t e u r : " + s t r ( machine . r e f l e c t e u r . p e r m u t a t i o n )) # texte a code t e x t e = " vvvvvvvvvvvvvvvvvvvvvvvvvvv " print ( "" ) print ( " t e x t e print ( t e x t e ) en c l a i r : " ) # affichage du texte code t e x t e c o d e = machine . c r y p t a g e ( t e x t e ) : ") print ( " t e x t e code print ( t e x t e c o d e ) # r e i n i t i a l i s a t i o n de la machine machine . r e i n i t i a l i s a t i o n ( ) # affichage du texte decode t e x t e c o d e = machine . c r y p t a g e ( t e x t e c o d e ) : ") print ( " t e x t e decode print ( t e x t e c o d e ) 14