Mémoire Magistère Steineur Marie-Aude 8 décembre 2006 Etude de la Primalité motivée par le besoin de Nombres Premiers dans le Chiffrement RSA 10130022 + 3761673 × 1065008 + 1 1 Table des matières I Cryptographie et complexité algorithmique 1 Le chiffrement RSA 1.1 Historique . . . . . . . . . . 1.2 Le chiffrement . . . . . . . . 1.3 Méthodes d’Exponentiation 1.4 Implémentation de RSA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 5 7 2 Théorie nécessaire à l’étude des algorithmes : La complexité 9 2.1 Outils mathématiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2 Complexité des opérations mathématiques . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.3 Classe de complexité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 II Etude de la primalité 15 3 Génération de deux nombres premiers 3.1 Etude des nombres premiers . . . . . . . . . . . . . . . . . . . . . 3.1.1 Une infinité de nombres premiers . . . . . . . . . . . . . . 3.1.2 Recherche d’un lien entre les nombres premiers . . . . . . 3.2 Recherche de générateurs de nombres premiers . . . . . . . . . . 3.2.1 Nombres de Fermat . . . . . . . . . . . . . . . . . . . . . 3.2.2 Nombres de Mersenne . . . . . . . . . . . . . . . . . . . . 3.2.3 Nombres premiers en progression arithmétique . . . . . . 3.2.4 Nombres premiers générés par des fonctions polynomiales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 15 15 17 17 18 19 19 4 Tests de primalités avant 2003 4.1 Le crible d’Erastosthène . . . . 4.2 Le test de Fermat . . . . . . . . 4.3 Algorithme de Solovay-Strassen 4.4 Test de Miller Rabin (1977) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 20 21 21 25 III . . . . . . . . (1976) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Un test de primalité déterministe de complexité polynomiale 5 L’algorithme d’Agrawal Kaya et Saxena 5.1 ”Primes is in P ”, premières idées . . . . 5.2 Existence du témoin d’AKS . . . . . . . 5.3 Complexité de l’algorithme . . . . . . . 5.4 Amélioration espérée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Démonstration du déterminisme de cet algorithme Table des matières Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 . . . . . . . . . . . . . . . . . . . . . . . . 29 29 30 31 32 32 2 3 Conclusion 36 Références 37 2 Introduction Depuis leur apparition, l’arithmétique et l’algèbre mêlent de façon confuse les calculs théoriquement possibles et effectivement réalisables. Ce n’est que depuis le développement des théories de l’informatique et de la complexité que des énoncés précis ont pu être formulés et illustrés par d’impressionnantes applications. Ainsi la sécurité des transactions interbancaires repose-t-elle sur la difficulté de la décomposition des grands nombres en facteurs premiers via des systèmes cryptographiques tels que le chiffrement RSA. Pour construire ces grands nombres, il faut générer de grands nombres premiers. S’il est théoriquement possible de vérifier la primalité d’un entier quelconque, ce n’est pas toujours techniquement réalisable. Ainsi les différents algorithmes efficaces testant la primalité sont-ils probabiliste : de nos jours il est courant d’utiliser des entiers ”premiers avec une très forte probabilité”. Mais un nouvel espoir apparaît avec l’algorithme d’Agrawal, Kayal et Saxena : ce le premier a avoir un temps de calcul qui croit de façon polynomiale avec la taille de l’entier à tester. Nous étudierons donc dans une première partie le chiffrement RSA comme exemple pour comprendre comment sont impliqués les nombres premiers dans la cryptographie. Nous nous attarderons également sur la notion de complexité, utile pour comparer les différents algorithmes. Dans une seconde partie, nous nous intéresserons a certaines caractéristiques des nombre premiers qui nous amèneront aux algorithmes classiques de primalité. La dernière partie sera consacrée à l’algorithme d’Agrawal, Kayal et Saxena. Dans tout ce texte, log désigne le logarithme en base deux, tandis que ln désigne le logarithme néperien. 3 Première partie Cryptographie et complexité algorithmique 1 Le chiffrement RSA 1.1 Historique Dans les années soixante-dix,Withfield Diffie et Martin Hellman veulent résoudre le problème de l’échange des clefs dans le but de s’envoyer des messages cryptés. Ils sont persuadés de l’existence d’une solution à ce problème. En effet, imaginons le scénario suivant : Alice envoie à Bob une clef placée dans un coffre en fer verouillé avec son cadenas. Bob lui renvoie la boîte en y ajoutant son propre cadenas. Alice enlève son cadenas et renvoie à Bob la boîte qu’il peut enfin ouvrir. Et Eve n’a pas pu intercepter leur clef. C’est le concept du chiffre asymétrique. Le problème est de trouver des fonctions mathématiques permettant un tel codage. En 1976, après deux ans de recherches, Hellman trouve enfin une solution utilisant l’arithmétique modulaire. Alice et Bob choisissent deux nombres premiers p et q. Par exemple, p = 23 et q = 3 – Alice choisit un nombre secret a = 6 – Alice envoie à Bob la valeur 36 ≡ 16 (mod 23) – Bob choisit à son tour un nombre secret b = 15 – Bob envoie à Alice la valeur 315 ≡ 12 (mod 23) – Alice peut maintenant calculer la clé secrète : 126 ≡ 9 (mod 23) – Bob fait de même et obtient la même clef qu’Alice : 1615 ≡ 9 (mod 23) En 1975, Ronald Rivest, Adi Shamir et Leonard Adleman, la curiosité éveillée par les idées de Diffie et Hellman se mirent eux aussi à la recherche de telles fonctions. En 1977, après une fête, Rivest trouve enfin une solution : C’est la naissance du code RSA (Rivest Shamir Adleman), c’est la naissance de la cryptograhie à clef publique. Selon le gouvernement anglais, ce système de cryptographie à clef publique aurait déjà été inventé en 1970 au GCHQ (Government Communications Headquarters). L’idée de clef publique était venue de James Ellis ( ”chiffrement non secret” selon sa propre nomenclature). Il chercha pendant trois ans sans trouver de fonctions mathématiques répondant à tant de contraintes. En 1973 arrive un mathématicien spécialiste en théorie des nombres : Clifford Cocks. On lui expose le problème, une demi-heure plus tard, il trouve une solution ; c’est la même que celle de Rivest. 1.2 Le chiffrement Ce chiffrement utilise l’arithmétique de Z/nZ où n est le produit de deux nombres premiers distincts (habituellement grands) p et q. Pour cet entier n, on a ϕ(n) = (p − 1)(q − 1) ; où ϕ est la fonction d’Euler. La description d’un tel système est : Chiffrement 1.1 : le chiffrement RSA 1. On pose n = pq où p et q sont premiers 4 2. 3. 4. 5. On cherche a, b ∈ Z/nZ tels que ab ≡ 1 (mod ϕ(n)) On définit la règle de chiffrement : e(x) = xb (mod n) ∀x ∈ Z/nZ On définit la règle de déchiffrement : d(y) = y a (mod n) ∀y ∈ Z/nZ Les valeurs n et b constituent la clef publique et p, q, a, la clef privée Démonstration de la logique d’un tel chiffrement : On a ab ≡ 1 (mod ϕ(n)) Donc il existe un entier t tel que ab = tϕ(n) + 1 . Donc pour tout entier x ∈ (Z/nZ)∗ , on a : (xb )a ≡ xtϕ(n)+1 (mod n) (xb )a ≡ (xϕ(n) )t x (mod n) et donc puisque ϕ(n) est l’ordre du groupe multiplicatif (Z/nZ)∗ (xb )a ≡ x (mod n) Exemple : Supposons qu’Alice choisisse 17 et 11 comme nombres premiers (habituellement, on les choisit plus grands mais les calculs deviennent alors plus compliqués ). Alice trouve alors n = 187, et ϕ(n) = 16 × 10 = 160. En choisissant a = 7, et b = 23, on obtient ab ≡ 1 (mod 160). On en déduit la fonction de chiffrement (qui peut être répertoriée dans une sorte d’annuaire : c’est la clef publique) : e(x) = x23 (mod 187) et la fonction de déchiffrement (c’est la clef privée, Alice est la seule à la posséder) : d(y) = y 7 (mod 187) Ainsi, si Bob veut envoyer à Alice le nombre 2, il calcule e(3) = 223 ≡ 162 (mod 187) Bob envoie donc à Alice le nombre 162. A son tour, Alice effectue l’opération d(162) = 1627 ≡ 2 (mod 187) Ainsi, Alice a bien reçu le message de Bob. 1.3 Méthodes d’Exponentiation On a remarqué que pour utiliser le chiffrement RSA, il nous est nécessaire de calculer xn (mod m). On se propoe donc ici de trouver une méthode ou ”algorithme ” effectuant le calcul de xn le plus ”rapidement” possible ; pour tout x tel que l’expression xn ait un sens. Le premier algorithme qui nous vient à l’esprit est celui qui consiste à calculer les valeurs successives x2 , x3 , . . . , xn : Algorithme 1.2 Exponentiation(x,n) : 5 1. z := x 2. Pour i = 1 jusqu’à n − 1 3. faire z := z ∗ x 4. Retourner z Il s’agit donc ici d’effectuer n − 1 multiplications. Un second algorithme est celui connu des chinois depuis environ vingt siècles. Il consiste à ne calculer que certaines puissances de x puis de les combiner pour trouver xn : Pour cela on utilise la décomposition binaire de n : k 0 X i ou , pour 0 ≤ i ≤ k n= ei 2 , où ei = 1 i=0 On a ainsi l’algorithme : Algorithme 1.3 Exponentiation rapide (x,n) : 1. y := x 2. z := x 3. tant que n > 1 m := bn/2c Si n > 2 × m faire alors :z := z × y n := m 4. z := z × y 5. Retourner z Calculons par exemple x15 par cette méthode : n m z y 15 1 x 15 7 x x2 7 3 x3 x4 3 1 x7 x8 1 x15 Etudions à présent le nombre N de multiplications effectuées par cet algorithme : On a : N = k + e0 + e1 + . . . + ek − 1, d’où la majoration : N ≤ 2k. De plus k vérifie 2k ≤ n < 2k+1 , donc k = blog nc, et ainsi N ≤ 2 log n. Une conséquence importante consiste dans le fait que cet algorithme comporte nettement moins de multiplications que le premier. 6 1.4 Implémentation de RSA Pour mettre en œuvre le chiffrement RSA, on utilise l’algorithme formel suivant : Algorithme 1.4 Implémentation de RSA 1. Génération de deux grands nombres premiers p et q 2. On pose n := pq et alors ϕ(n) = (p − 1)(q − 1) 3. On choisit b tel que 1 < b < ϕ(n) et gcd(b, ϕ(n)) = 1 4. On pose a := b−1 (mod ϕ(n)) 5. La clef publique est (n, b) et la clef privée (pq, a) Où ϕ représente la fonction d’Euler. Une attaque ”simple” de ce chiffre consiste à factoriser n ; et si cela peut se faire il est alors facile d’en déduire ϕ(n), et de calculer ainsi a à partir de b, comme le fait Bob. C’est pourquoi, pour rendre cette attaque plus ”difficile” (calculatoirement impossible), il convient de choisir p et q grands. Nous verrons dans les parties suivantes différents algorithmes permettant de trouver de tels nombres premiers. L’existence de a et b est claire. Pour vérifier que b est premier avec ϕ(n), on utilise l’algorithme d’Euclide Algorithme 1.5 Euclide (a,b) 1. r0 := a 2. r1 := b 3. m := 1 4. tant que rm 6= 0 j k qm := rm−1 rm faire rm+1 := rm−1 − qm rm m := m + 1 5. retourner rm Proposition 1.1 L’algorithme d’Euclide calcule le pgcd de a et b en effectuant au plus b2 log M c + 1 divisions entières ; où M = max(a, b). Démonstration : L’algorithme génère une suite r0 , r1 , . . . où r0 = a, r1 = b et ri+1 = ri−1 (mod ri ) pour i ≥ 1. Lemme 1.1 Si 1 ≤ b ≤ a, alors a (mod b) ≤ (a − 1)/2. 7 Preuve : Il est clair que a (mod b) ≤ b − 1 De plus jak b ≤ a − b. a (mod b) = a − b Donc a (mod b) ≤ min(a − b, b − 1). On a alors deux cas de figure : – Soit b ≤ (a + 1)/2, et alors b − 1 ≤ a − b, d’où a (mod b) ≤ b − 1 ≤ (a − 1)/2. – Soit b > (a + 1)/2, et alors a − b ≤ b − 1, d’où a (mod b) ≤ a − b ≤ a − (a + 1)/2 ≤ (a − 1)/2. D’après ce lemme, on a donc ai+1 ≤ ai−1 − 1 ai−1 ≤ . 2 2 Par récurrence sur i, on montre que a2i ≤ a0 a1 (i ≥ 0) et a2i+1 ≤ i (i ≥ 0). i 2 2 Soit ar ≤ 2−br/2c M pour r = 0, 1, . . . . L’algorithme se termine si ar < 1, ce qui survient uniquement si r est tel que 2−br/2c M < 1 ; c’est-à-dire r > 2 log M. Grâce à l’algorithme précédent, on peut trouver un entier b premier avec ϕ(n). Il nous reste encore à trouver le nombre a tel que ab ≡ 1 (mod ϕ(n)). Pour cela définissons les deux suites t0 , · · · , tm et s0 , · · · , sm par la relation de récurrence : si j = 0 si j = 0 1 0 0 si j = 1 1 si j = 1 et , sj = tj = tj−2 − qj−1 tj−1 si j ≥ 2 sj−2 − qj−1 sj−1 si j ≥ 2 Proposition 1.2 Pour 0 ≤ j ≤ m on a rj = sj r0 + tj r1 où les ri sont ceux calculés par l’algorithme d’Euclide. Démonstration : Elle se fait par récurrence sur j. Cette proposition nous permet donc de calculer pour deux entiers a et b les entiers t et s tels que (a, b) = sa + tb En particuler si a et b sont premiers entre eux alors t est l’inverse de b modulo a. On en déduit ainsi : Algorithme 1.6 Inverse(a,b) 8 a0 := a b0 := b t0 := 0 t := 1 j k 5. q := ab00 1. 2. 3. 4. 6. r := a0 − qb0 7. tant que r > 0 temp := (t0 − qt) t0 := t t := temp faire a0 := b0 b0 :=jr k q := ab00 r := a0 − qb0 (mod a) 8. si b0 6= 1 alors b n’a pas d’inverse modulo a sinon retourner t 2 2.1 Théorie nécessaire à l’étude des algorithmes : La complexité Outils mathématiques Ce paragraphe a pour but de comparer les taux d’accroissement de différentes fonctions et d’introduire les cinq symboles asymptotiques utilisés pour décrire ces taux. C’est en effet utile pour comparer dans un langage rigoureux, les vitesses d’exécution ou les complexités, de plusieurs algorithmes répondants aux mêmes problèmes. Par exemple supposons que nous disposions d’une méthode pour additionner deux matrices de taille n × n. Nous dirons que ”la méthode va prendre un temps 2n2 ”. Ainsi, si deux matrices de taille 100 × 100 peuvent être additionnées, avec cette méthode, en 1 minute de temps de calcul, des matrices 400 × 400 nécessiteraient 42 = 16 fois plus de temps, soit 16 minutes. On remarque que la constante ”2” n’interfert pas le temps de cacul. Nous avons donc besoin d’un langage permettant de préciser le temps de calcul en fonction de n. Les symboles utilisés pour ces comparaisons de taux d’accroissement sont : ”o” est petit o de ”O” est grand O de ”Θ” est théta de ”∼” est asymptotiquement égal à ”Ω” est oméga de Voici leur définition formelle : Définition 2.1 On dit que f (x) = o(g(x))(x → ∞) , (x) si limx→∞ fg(x) existe et vaut 0. 9 Cette notation exprime que f croît plus lentement que g quand x est très grand. Définition 2.2 On dit que f (x) = O(g(x))(x → ∞) , si ∃(C, x0 )tel que ∀x > x0 |f (x)| < Cg(x) . On omet en général de préciser que ”x → ∞”, puisque nous serons le plus souvent intéressés par les grandes valeurs des variables mises en jeu. Cette notation exprime le fait que f ne croît certainement pas plus vite que g. Définition 2.3 On dit que f (x) = Θ(g(x)) s’il existe des constantes c1 6= 0, c2 6= 0 telles que, pour tout x > 0,on ait c1 g(x) < f (x) < c2 g(x). On peut alors dire que f et g ont le même taux d’accroissement, puisque seules les constantes multiplicatives ne sont pas déterminées. Ce dernier est donc beaucoup plus précis que les deux précédents. Définition 2.4 On dit que f (x) ∼ g(x) , (x) si limx→∞ fg(x) = 1. C’est donc ce dernier symbole qui donne le plus d’informations :Il affirme que f et g ont le même taux d’accroissemment et que f /g tend vers 1 quand x → ∞. Définition 2.5 On dit que f (x) = Ω(g(x)), s’il existe > 0 et une suite x1 , x2 , · · · → ∞ telle que l’on ait pour tout j : |f (xj )| > g(xj ). De manière plus simple, on peut considérer ”Ω” comme une négation de ”o”. Ainsi par exemple, on peut être sûr que personne ne sera capable d’écrire un algorithme permettant de multiplier deux matrices de taille n × n comportant moins de n2 étapes de calcul, car il y a 2n2 données d’entrée. Nous pouvons donc dire que la mulplication de deux matrices n × n prend un temps Ω(n2 ). On utilise le symbole O˜(t(n)) pour O(t(n) × poly(log t(n))), où t(n) est une fonction quelconque de n, et poly un polynôme. Par exemple, O˜((log n)k ) = O((log n)k ∗ (log (log n)k )3 ) = O((log n)k+ )pour tout > 0, ici t(n) = (log n)k tandis que poly(x) = x3 . 2.2 Complexité des opérations mathématiques La vitesse de calcul d’un ordinateur est approximativement proportionnelle aux nombres de bits (abréviation de binary digit) utilisés. Les ordinateurs calculent en binaire, donc même si nous exprimons les entiers à l’aide de notation décimale, il nous faut utiliser l’équivalent binaire (l’arithmétique binaire s’effectuant comme à l’ordinaire). 10 On a ainsi par exemple : 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 Pour un entier n 1 1 1 1 1 1 0 0 0 0 0 donné, 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0 k = log n 0 1 0 0 0 × + + + 0 0 est le nombre de bits de n. Définition 2.6 On appelle opération binaire un processus qui consiste à additionner ou soustraire deux bits, prenant en compte tout reste ou retenue, et renvoyant la réponse avec le nouveau reste ou la nouvelle retenue. Définition 2.7 La complexité C d’un calcul arithmétique est le nombre maximal d’opération binaire à effectuer pour avoir le résultat en fonction de la taille d’entrée des données de ce calcul. On ne cherche donc qu’une borne supérieure de ce nombre d’opération. Lemme 2.1 Considérons deux entiers m et n tels que n ≥ m. On a alors : 1. C(calcul de m + n) = O(log n) 2. C(calcul de m − n) = O(log n) 3. C(calcul de m × n) = O((log n)2 ) 4. C(calcul de m/n) = O((log n)2 ) 5. C(calcul de gcd(m, n)) = O((log n)3 ) Preuve : 1. trivial 2. trivial 3. Remarquons que c’est d’une borne supérieure dont nous avons besoin. Considérons la multiplication : ∗ ∗ ··· ∗ ··· ··· ∗ ··· ∗k ∗k−1 ··· ··· ··· ··· ··· ··· ··· ∗ ··· ∗ ··· ∗m ··· ∗ ··· ∗m−1 ··· ∗ ··· ··· ··· ··· ··· ··· ··· ··· ··· ∗1 ∗1 ∗ ··· ··· ··· ··· ··· ∗ × + + Posons k = log n. Il n’y a pas plus de k + 2 opérations binaires à effectuer pour additionner les deux premières lignes car les entiers n’ont pas plus de k + 2 bits. Additionner ce résultat avec la troisième ligne ne requiert pas plus de k+3 opérations binaires. Par itération, on obtient que le nombre total d’opérations binaires n’excède pas : (k + 2) + (k + 3) + · · · + (l + k + 1) ≤ k(l + k + 1) ≤ k(2k + 1) = O((log n)2 ) 11 4. La méthode la plus simple consiste à compter ”combien de n sont contenus dans m”, et pour cela il faut soustraire un certain nombre de fois n à m. Cela ne prend donc pas plus de log nO(log n) = O((log n)2 ) opérations binaires. 5. Elle se fait en calculant la complexité de l’algorithme (Euclide(n,m)) : On a vu que cet algorithme nécessite O(log n) divisions, chacun de complexité O((log n)2 ) ; la complexité totale est donc O((log n)3 ). On s’intéresse maintenant aux opérations arithmétiques modulaires, c’est à dire aux opérations dans Z/nZ, pour n entier. Lemme 2.2 Soient a,b ∈ Z/nZ, et c un entier positif. 1. C(calcul de a + b (mod n)) = O(log n) 2. C(calcul de a − b (mod n)) = O(log n) 3. C(calcul de a × b (mod n)) = O((log n)2 ) 4. C(calcul de ac (mod n)) = O(log c × (log n)2 ) 5. C(calcul de a−1 (mod n)) = O((log n)3 ) Preuve : 1. Trivial 2. Trivial 3. Trivial 4. Elle se fait en calculant la complexité de l’algorithme (exponentiation rapide(a,c)) pour a élément de Z/nZ : On a vu que cet algorithme nécessite O(log c) multiplications modulaires, chacune de complexité O((log n)2 ). La complexité totale est donc O(log c(log n)2 ). 5. Elle se fait en calculant la complexité de l’algorithme (inverse(a,n)) : elle se détermine de façon similaire à celle du calcul du gcd à l’aide de l’algorithme d’Euclide. En fait, il est possible d’obtenir de meilleures complexités en utilisant des algorithmes plus fins (voir par exemple : Grahan Everes, Thomas Word ; An introduction to number theory). A l’aide de ces différentes complexités on peut calculer la complexité de l’algorithme classique de multiplication de deux polynômes de degré r dans Z/nZ : on a une complexité en O(r2 (log n)2 ). Mais si on utilise des transformée de Fourier rapide, on touve alors une complexité en O(r log r log n) = O˜(r log n). 2.3 Classe de complexité La théorie de la complexité est née des travaux d’Edmonds, de Cook et de Karp. Elle a pour but de lier le nombre de calculs binaires effectués lors de la résolution d’un problème à l’aide d’un algorithme, à la taille des données de ce problème. On utilise la nomenclature : – A pour algorithme – P pour problème – I pour l’ensemble des données (instance en anglais) On définit de plus : 12 – l’entier µ(I) : mesure de la longueur d’écriture de la donnée I (c’est à dire le nombre de bits). – l’entier C(A, I) : mesure le nombre d’étapes élémentaires (c’est à dire le nombre d’opérations binaires) de la résolution du problème P sur les données I à l’aide de l’algorithme A. C’est la complexité de l’algorithme A. Définition 2.8 Un algorithme A qui résoud un problème P à partir de données I est dit polynomial si pour toute donnée I, il existe un polynôme Q tel que C(A, I) ≤ Q(µ(I)). Un problème P est dit polynomial s’il existe un algorithme A polynomial résolvant ce problème. L’ensemble des problèmes polynomiaux est noté P ; on parle de la classe P. Définition 2.9 On dit que le problème P se réduit au problème P’ si : – Il existe un algorithme A qui transforme les données I de P en données I’ de P’ – Il existe un algorithme A’ qui transforme la solution S’ de P’ en solution S de P. On dit que P se réduit polynomialement à P’ si on a de plus A et A’ algorithmes polynomiaux. Définition 2.10 Soient O une famille d’objets ; et R une propriété. Les problèmes de la forme : ”l’objet o ∈ O a-t-il la propriété R ?” est un problème de décision. Définition 2.11 Soit P un problème de décision, et soit I les instances de ce problème pour lesquelles la réponses est OUI. On dit que le problème P appartient à la classe N P, s’il existe un algorithme polynomial en µ(I) qui à l’aide d’une information supplémentaire S permet de vérifier que la réponse est bien OUI pour ces instances I. N P ne veut pas dire non polynomial, mais non déterministe polynomial. Intuitivement, les problèmes dans N P sont l’ensemble des problèmes pouvant étre résolus en testant à l’aide d’un algorithme polynomial l’ensemble des solutions possibles. Définition 2.12 La classe co-N P est l’équivalent de la classe N P pour la réponse NON. remarque : On a les inclusions suivantes : P ⊂ N P et P ⊂ co − N P. Exemple : Un problème de co-N P : ”n est-il premier ? ” Etudions son opposé : ”n est-il composé ? ” pour n = pq Soit p un entier plus petit que n. Il est facile de voir à l’aide d’algorithmes de divisions et de multiplications (algorithmes polynomiaux) si l’entier p est ou non un facteur de n. Le problème ”n est-il composé ? ” est donc de classe N P. Donc le problème ”n est-il premier ? ” est de classe co-N P. Théorème 2.1 Théorème de Pratt : Tout nombre premier n ≥ 3 admet un certificat de primalité polynomial ; c’est à dire que le problème ”n est-il premier ?” est un problème de N P. 13 Démonstration : On utilise le lemme suivant : Lemme 2.3 Tout entier n > 1 est premier si et seulement si il existe a ∈ Z tel que : an−1 ≡ 1 (mod n) mais a(n−1)/q 6≡ 1 Ecrivons n−1= k Y qi (mod n) pour tout diviseur premier q de n − 1. pour qi premier. i=1 D’après ce qui précède, pour certifier que n est premier, il suffit de donner a et les qi et de demander de vérifier que k Y n−1= qi , i=1 On vérifie ensuite de façon récursive que a(n−1)/q 6≡ 1 (mod n) pour i = 1 . . . k, à l’aide d’algorithmes polynomiaux. Définition 2.13 – Un problème P est dit N P-difficile si tout problème de N P se réduit polynomialement à lui. – Un problème P de N P est dit N P-complet si tout problème de N P se réduit polynomialement à lui. Le théorème de Cook nous assure l’existence de problèmes N P-complet, mais bien qu’il soit très intéressant, je ne m’y attarde pas ici. On sait de façon triviale que P ⊂ N P, mais la réciproque P ⊃ N P (résumée généralement à P = N P), loin d’être triviale est l’un des problèmes fondamentaux (et intéressants) en informatique théorique posée en 1970 pour la première fois. Il revient à savoir si l’on peut résoudre un problème N P-complet avec un algorithme polynomial. Ainsi, jusqu’en 2003, ne savions nous pas si le problème "n est-il premier ? " était de classe P. Ce problème sera étudié plus loin avec le test d’Agrawal, Kayal et Saxena. 14 Deuxième partie Etude de la primalité 3 Génération de deux nombres premiers 3.1 3.1.1 Etude des nombres premiers Une infinité de nombres premiers Théorème 3.1 L’ensemble des nombres premiers est infini Démonstration : La démonstration d’Euler est la plus connue ; cependant nous allons donner ici celle d’Hurwitz : elle permet d’introduire en plus la suite de Fermat, étudiée plus bas. Soit a1 < a2 < · · · < an < · · · une suite infinie de nombres naturels premiers entre eux. Cela implique qu’ils n’ont aucun facteur premier en commun. Donc si : p1 est un facteur premier de a1 ; p2 est un facteur premier de a2 ; ··· pn est un facteur premier de an ; ··· Alors p1 p2 · · · pn · · · sont tous distincts. Et puisque l’on a supposé la suite (an )n infinie, on en déduit l’infinité de l’ensemble des nombres premiers. Mais il reste à montrer l’existence d’une telle suite. n Lemme 3.1 Les nombres de Fermat définis par Fn = 22 +1 constituent une suite infinie de nombres premiers entre eux. Preuve : – Montrons par récurrence sur l’entier n que Fn − 2 = F0 ∗ F1 ∗ · · · ∗ Fn−1 : On a F1 − 2 = 3 = F0 . supposons l’égalité vraie pour n ∈ N, et montrons la au rang suivant : Fn+1 − 2 = 22 n+1 n n − 1 = (22 − 1)(22 + 1) = (Fn − 2) × Fn Donc la propriété est vraie quelque soit n ∈ N. – Soit p un facteur commun à Fn et Fm . On peut supposer n < m, alors p divise aussi Fm − 2. Ce qui implique que p est pair, absurde car tous les nombres de Fermat sont impairs. Puisqu’il existe une infinité de nombres premiers, on peut se demander s’il existe un lien entre eux. 3.1.2 Recherche d’un lien entre les nombres premiers répartition des nombres premiers : Les différentes démonstrations de l’infinité des nombres premiers ne donnent pas d’indices quant aux différentes valeurs prises par ces nombres ; en effet aucune d’elles n’est 15 constructive. Mais on peut estimer le nombre de nombres premiers inférieurs à N : c’est la fontion π(N ) (Elle est notée ainsi car elle est souvent associée au nombre π). La méthode la plus simple pour trouver la valeur de π(N ) est de prendre une table des nombres premiers et de les compter... on n’a pas encore trouvé de formule générale. En 1972, Gauss alors agé de 15 ans, conjecture que : Théorème 3.2 Théorème des nombres premiers : π(N ) ∼ x ln(x) Ce théorème fut démontré de façon indépendante en 1896 par deux analystes : Hadmard et De La Vallée Poussin (pour une démonstration, on peut se référer au cours d’Analyse complexe de Mme Audin). La spirale d’Ulam : Lors d’une conférence d’un congrès en 1963, alors qu’il s’ennuyait, Stanislav Ulam écrivit une spirale de nombres entiers... Puis il griffonna ceux qui étaient premiers... A sa grande surprise, ceux-ci avaient tendance à se situer sur des droites : Ulam utilise alors l’ordinateur MANIAC pour obtenir les nombres premiers de la spirale des entiers de 1 à 164000... Et on remarque alors que même près des bords de la photographie obtenue, les nombres continuent à s’aligner "sagement" : 16 3.2 3.2.1 Recherche de générateurs de nombres premiers Nombres de Fermat Proposition 3.3 Soient a et c deux entiers non nuls. Si a est impair ou si c a un facteur impair, alors l’entier ac + 1 est composé Démonstration : 1. Supposons que a = 2j + 1, pour j entier ; alors : ac + 1 = (2j + 1)c+1 = c X Ckc ∗ 2k ∗ j k + 2 k=2 c Et donc a + 1 est divisible par 2. 2. Supposons que c = k(2m + 1), pour m et k entiers strictement positifs ; alors : ac + 1 = (ak + 1) ∗ (a2km − ak(2m−1) + · · · + 1). Et donc ac + 1 est composé. 17 Lemme 3.2 Si ac + 1 est premier, alors a est pair et c est une puissance de deux. Preuve : C’est la proposition précédente. Fermat, connaissant ce lemme, définit les nombres : n Fn = 22 + 1. Il remarque que ces nombres sont premiers pour n = 0, .., 4, et conjecture alors, qu’ils le sont pour tout entier n. Or F5 ayant déjà dix chiffres, il lui devient difficile de vérifier s’il est bien premier. Hélas... Théorème 3.4 Théorème d’Euler : 641 divise F5 . Démonstration : C’est un magnifique jeu de nombres.... On a que 641 = 24 + 54 et 641 = 5 ∗ 27 + 1. De plus 232 = 24 ∗ 228 = 641 ∗ 228 − (641 − 1)4 = 641K − 1. A ce jour on n’a pas encore trouvé d’autres nombres de Fermat premiers. Il semble alors que cette conjecture puisse être remplacée par : "les nombres 2 + 1, 22 + 2 1, 22 + 1, · · · sont tous premiers" ; mais F16 n’est pas premier... ce qui met en défaut cette conjecture. 3.2.2 Nombres de Mersenne Proposition 3.5 Soient deux entiers strictement positifs a et c. Si a > 2 ou si c est composé, alors ac − 1 est composé. Démonstration : – Supposons que c = d ∗ e ; alors ac − 1 = (ae − 1)(ae(d−1) + ae(d−2) + · · · + 1) – Supposons que a > 2 ; alors ac − 1 = (a − 1)(ac−1 + ac−2 + · · · + 1) Lemme 3.3 Si ac − 1 est premier, alors a = 2 et c est premier. preuve : C’est la proposition. Les nombres de Mersenne sont les nombres Mp = 2p −1, avec p entier premier. Mersenne a conjecturé qu’il existe une infinité de nombres premiers écrits sous cette forme ; la démonstration, trouvée plus tard, étant assez difficile ne sera pas abordée ici. Théorème 3.6 Soit p un nombre premier. 1. S’il existe k entier stritement positif tel que p = 4k + 3, alors 2p + 1 est premier si et seulement si 2p + 1 divise Mp . 2. Si 2p + 1 divise Mp , alors 2p + 1 est premier. 18 Démonstration : Supposons que 2p + 1 est premier ; alors 2p + 1 ≡ −1 (mod 8), et donc 2p ≡ 1 (mod 2p + 1). Réciproquement, supposons que p 2 ≡1 (mod 2p + 1) et que 2p + 1 = k Y pαi i où pi est premier. i=1 On a de plus que 2ϕ(2p+1) ≡ 1 (mod 2p + 1) (où ϕ est la fonction d’Euler), donc p divise ϕ(2p + 1). Or k Y ϕ(2p + 1) = pαi i −1 (pi − 1) i=1 Ce qui implique qu’il existe un entier i tel que p divise pi − 1. Or il existe un entier n tel que 2p + 1 = npi . Donc si n = 1, la démonstration est finie. Sinon n > 2 donc p > pi − 1 et on a une contradiction. Le quarante-quatreième nombre de Mersen a été trouvé le 6 septembre 2006 à l’aide de GIMPS est vaut : 232582657 − 1 3.2.3 Nombres premiers en progression arithmétique Théorème 3.7 Théorème de Dirichlet : Soient deux entiers non nuls a et d, premiers entre eux tels que d ≥ 2. Alors la progression arithmétique a, a + d, a + 2d, · · · contient une infinité de nombres premiers. Ce théorème, démontré en 1837, est un théorème fondamental de la théorie des nombres. Admettons-le ici. Le problème est alors, comme toujours, de savoir lesquels sont premiers ; ce qui nous amène à nous demander quelle est la densité de ces nombres dans cette suite. De La Vallée Poussin a établi le résultat supplémentaire de densité suivant : Proposition 3.8 Soient d ≥ 2 et a 6= 0 deux entiers premiers entre eux. On définit π(d, a, x) = # {p premier tel que p ≥ x et p ≡ a (mod d)} ; et on a : x . π(d, a, x) ∼ ϕ(d) ∗ ln(x) C’est à dire que l’ensemble des nombres premiers dans la progression arithmétique a, a + d, a + 2d, · · · lorsque a et d sont premiers entre eux a pour densité naturelle 1/ϕ(d) par rapport à l’ensemble des nombres premiers. Admettons aussi cette proposition. 3.2.4 Nombres premiers générés par des fonctions polynomiales Une généralisation des suites arithmétiques peut être effectuée au niveau polynomial. C’est ce qu’exprime la spirale d’Ulam : en effet, les nombres premiers alignés sur une 19 droite dans une direction sont les valeurs successives d’un trinôme. Ainsi, la suite de nombres 5, 19, 41, 71 est la suite des valeurs du polynôme 4x2 + 10x + 5 pour les valeurs sucessives de la variable. Le générateur de nombres premiers le plus célebre est x2 + x + 41 ; il est dù à Euler. Ce polynôme nous fournit une suite ininterrompue de 40 nombres premiers. En fait, l’interpolation polynômiale nous permet de construire un polynôme, nous donnant ce genre de suite. On peut se demander alors s’il existe un polynôme de degré k qui ne donne que des nombres premiers pour toute valeur entière de la variable. Proposition 3.9 Soit un polynôme P (x) = xk ak + · · · + a0 . Si l’entier P (n) est premier pour tout entier n, alors le polynôme P est constant. Démonstration : Montrons-la par l’absurde : Supposons qu’un tel polynôme P non constant existe ; alors P (bxc) ∈ (N)∗ . Et on a en particulier que P (0) = a0 ce qui implique que a0 est premier. De plus, lim supx→∞ P (bxc) = +∞ (car la suite des nombres premiers diverge vers l’infini). Donc il existe N ∈ N tel que P (N ) > a0 ; d’où l’existence d’un entier k tel que P (ka0 ) > a0 . Or ao divise P (ka0 ), ce qui est impossible puique P (ka0 ) est censé être premier... d’où la contradiction. On montre le même résultat avec des fonctions à plusieurs variables... Il semble donc que la recherche exhaustive de générateurs simples de nombres premiers soit vaine... Il reste donc à prendre un nombre au hasard et à verifier qu’il est premier... 4 Tests de primalités avant 2003 Pour trouver des nombres premiers, on choisit en pratique des nombres aléatoires et on teste leur primalité jusqu’à l’obtention d’un nombre premier. En utilisant le théorème des nombres premiers, on voit que la probabilité de découvrir un entier p premier compris entre 1 et N est d’environ 1/ ln N . 4.1 Le crible d’Erastosthène La méthode la plus simple qui nous vient à l’esprit pour tester la primalité d’un nombre est celle des divisions successives... mais dès que le nombre à tester devient grand, cette méthode devient (très) laborieuse Cette méthode est celle du crible d’Erastosthène, méthode vieille de plus de 2000 ans. On peut ainsi construire : Algorithme 4.1 Erastosthène (n) 1. Pour i := 2 jusqu’à √ faire : n Si n ≡ 0 (mod i) Alors retourner ”n est composé” 2. Retourner ”n est premier”. √ Proposition 4.1 Le crible d’Erastosthène est de complexité O( n(log n)2 ). 20 Démonstration : Il suffit de vérifier qu’il n’existe pas de diviseurs entiers de n parmi les entiers (autres que 1) inférieurs à√la racine carrée de n. Si n est composé, n a un diviseur d différent de 1 et √ n tel que d < n. divisions dont le temps de calcul est en O((log n)2 ), ce qui donne Il faut donc faire n √ une complexité en O( n(log n)2 ). 4.2 Le test de Fermat Supposons que l’on dispose d’un entier dont on veut tester la pimalité. Si l’on trouve un entier a tel que an−1 6≡ 1 (mod n), alors on a la certitude que l’entier n n’est pas premier. Cependant est-il vrai que si an−1 ≡ 1 (mod n), alors n est premier ? Non, en effet on a par exemple 2341 ≡ 2 (mod 341) or 341 = 11 ∗ 31. De tels nombres sont dits pseudo-premiers en base a. De plus, il existe des nombres composés dit de Carmichael tels que pour tout entier a premier avec n, an−1 ≡ 1 (mod n). Cependant de tels exemples sont rares et on peut donc envisager d’adopter ce critère comme un test probabiliste de primalité, appelé test de Fermat. Algorithme 4.2 Test de Fermat (n) : 1. Choisir un entier aléatoire a 2. b := an−1 (mod n) 3. Si b = 1 alors retourner ”n est premier” sinon retourner ”n n’est pas premier” Le test de Fermat est un algorithme de Monte-Carlo négatif pour la question de primalité ; c’est-à-dire que la réponse négative ”est composé” est toujours vraie ; mais la positive ”est premier” peut être fausse. Cependant pour n très grand, il faut être très malchanceux pour tomber sur un pseudo-premier. Ainsi, pour n de l’ordre de 10100000 , la probabilité d’erreur est inférieure à 1.23 ∗ 10−1058 (admettons ce résultat). Cet algorithme est de complexité O((log n)3 ), en effet, le seul calcul à effectuer est une exponentiation modulaire de complexité O(log(n − 1)(log n)2 ) = O((log n)3 ) . 4.3 Algorithme de Solovay-Strassen (1976) Cet algorithme le symbole de Jacobi. Ainsi, pour n > 1 entier impair, si n est utilise a (n−1)/2 (mod n) (c’est le théorème d’Euler). Mais si n est un entier premier alors n ≡ a composé, il est possible que cette égalité soit tout de même vérifiée ; on dit alors que n 10 est pseudo-premier pour la base a. Ainsi, 91 = −1 ≡ 1045 (mod 91) or 91 = 7 ∗ 13. On a a remarque de plus que n = 0 ⇔ (a, n) > 1 ; donc si n = 0 avec 1 ≤ a ≤ n − 1 alors n est composé On peut alors construire : 21 Algorithme 4.3 Solovay-Strassen (n) : 1. Choisir un entier aléatoire a tel que 1 ≤ a ≤ n − 1 2. x := na 3. Si x = 0 alors retourner ”n est composé” 4. y := a(n−1)/2 (mod n) ; 5. Si x ≡ y (mod n) alors retourner ”n est premier” sinon retourner ”n est composé” Il nous est donc nécessaire d’avoir un algorithme qui calcule le symbole de Jacobi a n : Algorithme 4.4 Jacobi(a,n) : 1. Si n ≡ 1 (mod 2) et a ≥ n alors retourner Jacobi(a (mod n) ;n) 2. Si n ≡ 1 (mod 2) et a = 2 alors si n ≡ ±1 (mod 8) alors retourner 1 sinon retourner -1 3. Si n ≡ 1 (mod 2) et a ≡ 0 (mod 2) alors retourner Jacobi(2,n)*Jacobi(a/2 ;n) 4. Si n ≡ 1 (mod 2) et a ≡ 1 (mod 2) alors si n ≡ 3 (mod 4) et a ≡ 3 (mod 4) alors retourner Jacobi(n,a) sinon retourner -Jacobi(n,a) L’algorithme de Solovay-Strassen est donc un algorithme de Monte-Carlo négatif pour la question de primalité . Proposition 4.2 L’algorithme de Solovay-Strassen est un algorithme polynomial en O((log n)3 ) Démonstration : On a vu que l’on peut calculer a(n−1)/2 (mod n) en temps O((log n)3 ) ; reste à calculer la complexité de l’algorithme qui permet le calcul du symbole de Jacobi. Lemme 4.1 Soient b et n deux entiers tels que 1 ≤ b ≤ n. Alors : C(calcul de nb ) = O((log n)3 ). Preuve : On doit supposer que gcd(b, n) = 1 Choisissons un entier b1 tel que b1 ≡ b (mod n) et − n2 ≤ b1 ≤ n2 . Alors b2 n b = ± avec 0 ≤ b2 ≤ n n 2 22 Et donc 1 b2 b = ± ± . n n n Si b2 = 2 alors on peut utiliser la formule qui calcule n2 . Si b2 est impair, alors on peut appliquer le théorème de la réciprocité quadratique pour voir que : b 1 n 1 n (mod b2 ) = ± ± = ± ± , n n b2 n b2 et donc 1 b3 b = ± ± n n b2 avec 1 ≤ b3 ≤ b2 ≤ n . 2 A chaque répétition de ces étapes, le dénominateur est réduit par un facteur de 2, donc il y a au plus O(log n) étapes. Chaque étape nécessite deux réductions modulaires, de temps O((log n)2 ). Finalement la complexité totale est : O(log n)O((log n)2 ) = O((log n)3 ). La complexité totale de l’algorithme de Solovay-Strassen est donc : O((log n)3 ) + O((log n)3 ) = O((log n)3 ). Proposition 4.3 L’algorithme de Solovay-Strassen annonce qu’un nombre est premier avec une probabilité d’erreur inférieure à 1/2. Démonstration : Soit n a G(n) = a ∈ Z/nZ∗ a(n−1)/2 ≡ n (mod n) o Observons que G(n) est un sous groupe de Z/nZ∗ . De plus on a : Lemme 4.2 Soit n entier impair, alors G(n) = (Z/nZ)∗ si et seulement si n est premier. Preuve : D’après le théorème d’Euler, si n est premier alors G(n) = (Z/nZ)∗ . Montrons la réciproque. Supposons n entier impair. – Si p2 divise n pour p nombre premier, alors il existe un entier a d’ordre p(p − 1). Or p − 1 ne divise pas n − 1, donc an−1 6= 1. – Si n = p1 p2 . . . pr , avec r ≥ 2 et pi tous premiers distincts, choisissons grâce au lemme Chinois un entier a tel que : a ≡ 1 (mod p2 , . . . , pr ) et non carré modulo p1 . Alors : a ≡ −1 (mod n) mais an−1 ≡ 1 (mod p2 . . . pr ). n Donc a(n−1)/2 n’est pas congru à −1 modulo n. 23 Ainsi, si n est composé, l’indice de G(n) est supérieur ou égal à 2. On a donc, puisque nous travaillons avec des groupes finis : |G(n)| ≤ |(Z/nZ)∗ | n−1 ≤ . 2 2 Ainsi en prenant a aléatoirement, on a au moins une chance sur deux d’avoir a ∈ / G(n). On peut à présent imaginer que l’on ait pris un entier aléatoire n et que l’on ait testé m fois sa primalité à l’aide de l’algorithme de Solovay-Strassen. Avec quelle probabilité peut on dire que n est premier ? Pour ce faire, définissons les évènements suivants : – A : ”le nombre aléatoire n est composé” – B : ”l’algorithme répond ”n est premier” m fois” Notons  l’évènement contraire à A : Il représente l’évènement : ”le nombre aléatoire n est premier” D’après l’étude précédente, on a Pr[B|A] ≤ 2−m . La probabilité qui nous intéresse est cependant Pr[A|B] ; calculons-là à l’aide du théorème de Bayes. Supposons que N < n < 2N ; d’après le théorème des nombres premiers, le nombre de nombres premiers compris entre N et 2N est environ : 2N N N n − ≈ ≈ . ln 2N ln N ln N ln n De plus il y a environ N/2 ≈ n/2 nombres impairs entre N et 2N , on peut donc utiliser l’estimation : 2 Pr[A] ≈ 1 − ln n Nous pouvons maintenant calculer : Pr[A|B] = = Pr[B|A]Pr[A] Pr[B] Pr[B|A]Pr[A] Pr[B|A]Pr[A] + Pr[B|Â]Pr[Â] Pr[B|A](1 − ln2n ) ≈ Pr[B|A](1 − ln2n ) + ln2n = Pr[B|A](ln n − 2) Pr[B|A](ln n − 2) + 2 ≤ 2−m (ln n − 2) 2−m (ln n − 2) + 2 ln n − 2 ln n − 2 + 2m+1 Ainsi en testant m fois un entier à l’aide de l’algorithme de Solovay-Strassen, on obtient une probabilité d’erreur : = 24 m 1 2 5 10 20 30 50 100 4.4 probabilité d’erreur 0,989 0,978 0,847 0,147 0, 168 × 10−3 0, 164 × 10−6 0, 157 × 10−12 0, 139 × 10−27 Test de Miller Rabin (1977) Ce test est un raffinement du test de Solovay-Strassen. Il est fondé sur la remarque suivante : Si a(n−1)/2 (mod n) = 1 et si (n−1)/2 est encore pair, alors a(n−1)/4 (mod n) = ±1 si n est premier. On en déduit : Algorithme 4.5 Miller-Rabin (n) : Ecrire n − 1 = 2k m, où m est impair Choisir un entier aléatoire a, 1 ≤ a ≤ n − 1 b := am (mod n) Si b ≡ 1 (mod n) alors retourner ”n est premier” 5. Pour i de 0 jusqu’à k − 1 Si b ≡ −1 (mod n) alors retourner ”n est premier” Faire : sinon b := b2 (mod n) 1. 2. 3. 4. 6. retourner ”n est composé” Proposition 4.4 Le Test de Miller-Rabin est un algorithme de Monte-Carlo négatif pour le problème de primalité. Démonstration : Montrons-le par l’absurde : supposons que cet algorithme réponde "n est composite" pour un nombre premier n. On a que n − 1 = 2k m avec m entier impair ; et d’après cette réponse, on en déduit que ak n’est pas congru à 1 modulo n. Considérons maintenant la suite des valeurs successives de l’entier b : Puisque b est élevé au carré à chaque nouvelle itération de la boucle, cette suite est : am , a2m , · · · , a2 k−1 m . i D’après la réponse de l’algorithme on en déduit que a2 m n’est pas congru à −1 modulo n pour i entier tel que 0 ≤ i ≤ k − 1. k En utilisant l’hypothèse que n est premier, d’après le théorème de Fermat, on a a2 m ≡ 1 k−1 (mod n). Ainsi, l’entier a2 m est une racine carrée de l’unité modulo n ; et étant donné 25 k−1 que n est premier, l’entier 1 n’admet pour seule racine que ±1. Or a2 m n’est pas congru k−1 à −1 modulo n donc a2 m ≡ 1 (mod n). En itérant cet argument, on obtient que am ≡ 1 (mod n) ; ce qui est impossible. Proposition 4.5 L’algorithme de Miller-Rabin est polynomial, de complexité O((log n)3 ). Démonstration : Le seul calcul côuteux de cet algorithme est le calcul de am (mod n) et de b2 (mod n) (à effectuer au plus k fois) ; calcul qui se fait en O((log n)3 ). Proposition 4.6 L’algorithme de Miller-Rabin annonce qu’un nombre n est pemier avec une probabilité d’erreur inférieure à 1/4 pour tout n > 9. Définition 4.1 On dit qu’un entier n est un pseudo premier fort en base a, si n est un entier composé impair : n − 1 = 2s t avec t impair et si on a soit at ≡ 1 (mod n) soit i a2 t ≡ −1 (mod n) pour un i tel que 0 ≤ i ≤ s − 1. Si n est pseudo premier fort en base a, alors pour ce choix de a, l’algorithme annoncera ”n est premier”. Démonstration : Définissons l’ensemble G(n) : G(n) = {a (mod n) |: n est un pseudo premier fort en base a} . Montrons que |G(n)| ≤ 14 ϕ(n) pour n > 9 ; où ϕ(n) = |(Z/nZ)∗ |. Pour cela, démontrons préalablement quelques lemmes. Lemme 4.3 Soit n un entier impair composé avec n − 1 = 2s t, t entier impair. Soit ν(n) le plus grand entier tel que 2ν(n) divise p − 1 pour tout facteur premier p de n. ν(n)−1 t Si n est un pseudo premier fort en base a, alors a2 ≡ ±1 (mod n). Preuve : – Si at ≡ 1 (mod n), alors c’est clair. ν(n)−1 t – Supposons que a2 ≡ −1 (mod n), et soit p un facteur premier de n, alors 2ν(n)−1 t a ≡ −1 (mod p). Soit k l’ordre multiplicatif de a dans Fp , alors k divise 2i+1 t, mais ne divise pas 2i t. Donc la puissance de 2 dans la décomposition en facteurs premiers de k doit être 2i+1 . Mais puisque k divise p − 1 (car ap−1 ≡ 1 (mod p)), 2i+1 divise p − 1, et cela pour tout facteur premier p de n. Et on a donc i + 1 ≤ ν(n). ν(n)−1 t Ainsi a2 ≡ +1 (mod n) ou −1 (mod n) selon que i+1 < ν(n) ou i+1 = ν(n). Lemme 4.4 Avec les mêmes notations que dans le lemme précédent, définissons n o 2ν(n)−1 t G(n) = a (mod n) a ≡ ±1 (mod n) Soit ω(n) le nombre de différents facteurs premiers de n. On a alors : Y G(n) = 2 ∗ 2(ν(n)−1)ω(n) gcd(t, p − 1). p|n 26 Preuve : Posons m = 2ν(n)−1 t, et suposons que la décomposition en facteurs premiers de n soit pj11 . . . pjkk où k = ω(n). On a am ≡ 1 (mod n) si et seulement si am ≡ 1 (mod pji i ) pour i = 1 . . . k. Pour un nombre premier impair p, et un entier non nul j, le groupe Z/pZ∗ est cyclique d’ordre pj−1 (p − 1) ; et il existe donc une racine primitive modulo pj . Ainsi, le nombre de solutions a (mod pji i ) de l’équation am ≡ 1 (mod pji i ) est : gcd(m, pji i −1 (pi − 1)) = gcd(m, pi − 1) = 2ν(n)−1 gcd(t, pi − 1). (La première égalité est verifiée car m|(n − 1), et donc m n’est pas divisible par pi ) D’après le Lemme Chinois, le nombre de solutions de l’équation am ≡ 1 (mod n) est : k Y 2µ(n)−1 gcd(t, pi − 1) = 2(µ(n)−1)ω(n) i=1 Y gcd(t, p − 1). p|n Pour finir, il nous faut encore montrer qu’il y a exactement autant de solutions pour l’équation am ≡ −1 (mod n). Remarquons que am ≡ −1 (mod pji i ) si et seulement si a2m ≡ 1 (mod pji i ) et a2m 6≡ 1 (mod pji i ). Puisque 2ν(n) divise pi − 1, le nombre de solutions de l’équation am ≡ −1 (mod n) est : 2ν(n) gcd(t, pi − 1) − 2ν(n)−1 gcd(t, pi − 1) = 2ν(n)−1 gcd(t, pi − 1). Ainsi le cardinal recherché est bien celui trouvé, et le lemme est prouvé. Revenons à la démonstration du théorème. D’après le premier lemme, il suffit de montrer que G(n)/ϕ(n) ≤ 1/4 pour tout entier n impair composé plus grand que 9. La fonction d’Euler est donnée par : Y Y 1 ϕ(n) = n (1 − ) = pa−1 (p − 1). p a p ||n p|n Où pa ||n signifie que p est un diviseur de n et que a est la valuation p-adique de n. Et donc d’après le second lemme on a : ϕ(n) 1 Y a−1 p−1 = p . ν(n)−1 G(n) 2 a 2 gcd(t, p − 1) p ||n Chaque facteur p − 1/2ν(n)−1 gcd(t, p − 1) est un entier pair ; donc ϕ(n)/G(n) est un entier. Etudions à présent les différents cas de figure suivant les valeurs prises par ω(n) : – Si ω(n) ≥ 3 : Il s’ensuit que ϕ(n)/G(n) ≥ 4 ; et on a le résultat attendu. – Si ω(n) = 2 : – Si n = pq, avec p < q entier et 2ν(n)+1 |(q − 1), alors 2µ(n)−1 gcd(t, q − 1) ≤ premier (q − 1)/4 et alors ϕ(n)/G(n) ≥ 4. 27 – Si n = pq, avec p < q entier premier et 2ν(n) ||(q − 1), remarquons alors que n − 1 ≡ p − 1 (mod q − 1), et donc (q − 1) ne divise pas (n − 1). Ce qui implique qu’il existe un nombre premier impair divisant q − 1 à une plus grande puissance ν(n)+1 que celle divisant |(q−1), alors 2µ(n)−1 gcd(t, q−1) ≤ (q−1)/6, n−1 ; et donc 2 d’où ϕ(n)/G(n) ≥ 6. – Si n ne s’écrit pas sous la forme pq avec p et q entier premier, alors le prouit des variables pa−1 est supérieur ou égal à 3 ; et donc ϕ(n)/G(n) ≥ 6. – Si ω(n) = 1 : On a alors n = pa avec a ≥ 2, et ainsi ϕ(n)/G(n) = pa−1 . On en déduit que ϕ(n)/G(n) ≥ 5 (car on a écarté le cas pa = 9), ce qui achève la démonstration. 28 Troisième partie Un test de primalité déterministe de complexité polynomiale 5 5.1 L’algorithme d’Agrawal Kaya et Saxena ”Primes is in P ”, premières idées L’idée du test d’Agrawal, Kayal et Saxena se base sur une généralisation du petit théorème de Fermat. Lemme 5.1 Soient deux entiers a et n, premiers entre eux. Alors, n est premier si et seulement si (X + a)n ≡ (X n + a) (mod n) dans l’anneau Z[X]. Démonstration : Pour 0 < q < n, le coefficient de X q dans ((X + a)n − (X n + a)) est Cnq an−q . – Supposons l’entier n premier. Alors Cnq ≡ 0 (mod n) et chacun des coefficients est nul. – Supposons l’entier n composé. Considérons alors un facteur premier q de n. Soit k la valuation q-adique de n. Alors q k ne divise pas Cnq , et il est premier avec an−q . Ainsi le coefficient de X q est non nul modulo n. On en déduit que ((X + a)n − (X n + a)) n’est pas identiquement nul dans Z/nZ. Ce lemme suggère un test simple de primalité : pour un entier n donné, on choisit un entier a, et on regarde si la congruence est vérifiée. Cependant, évaluer directement ces polynômes prend un temps Ω(n), puisqu’il faut évaluer dans le meilleur des cas n coefficients. Une première idée serait d’utiliser le test probabiliste d’identité développé par Agrawal et Biswas : Ce test d’une probabilité d’erreur bornée et de temps d’exécution polynomial, évite complètement le développement du polynôme (cf l’article : M.Agrawal et S.Biswa, Primality and identity via Chinese remainding, Journal of the ACM 50(2003),429 443 ). Hélas, ce test est loin d’étre compétitif avec celui de Miller et Rabin. Une autre idée serait de réduire le nombre de coefficients en évaluant (X + a)n et X n + a modulo un polynôme de la forme X r − 1 dans Z/nZ, pour un entier r choisi assez petit. En d’autre terme, verifier l’équation suivante : (X + a)n ≡ X n + a (mod X r − 1, n) Il est clair, d’après le lemme précédent que pour tout nombre premier n, l’équation est vérifiée pour toutes valeurs de a et r. Le problème consiste dans l’existance de nombres composés qui vérifient aussi cette équation pour de nombreuses valeurs de a et r. Cependant il est possible de choisir un entier r (dépendant de n) tel que si l’équation est vérifiée pour certaines valeurs de a alors n est premier. Les valeurs que doit prendre a ainsi que la valeur appropriée de r sont bornées par un polynome en log n ; et ainsi nous obtenons un algorithme déterministe de temps polynômial pour la question de primalité. Définition 5.1 Soit n un entier. On appelle témoin d’AKS de n, un entier r premier avec n tel que l’ordre de n dans Z/rZ∗ soit supérieur ou égal à (log n)2 29 Algorithme 5.1 Agrawal-Kayal-Saxena(n > 1) : 1. Si n = ab pour a ∈ N et b > 1 alors retourner ”n est composé” 2. Trouver le plus petit témoin d’AKS r 3. Si 1 < gcd(a, n) < n pour a ≤ r alors retourner ”n est composé” 4. Si n < r alors retourner ”n est premier” jp k 5. Pour a := 1 jusqu’à ϕ(r) log n Si (X + a)n 6≡ X n + a (mod X r − 1, n) Faire : alors retourner ”n est composé” 6. retourner ”n est premier” 5.2 Existence du témoin d’AKS Nous aurons besoin du lemme suivant : Lemme 5.2 Pour m ≥ 7, LCM(m) ≥ 2m ; où LCM(m) définit le plus petit commun multiple de tous les entiers inférieurs ou égaux à m. Notons σr (n) l’ordre de n dans (Z/rZ)∗ . Proposition 5.1 Pour tout entier n > 1 il existe un témoin d’AKS r tel que r ≤ max(3, d(log n)5 e). Démonstration : Si n = 2, alors r = 3 est un témoin d’AKS pour n. Supposons donc n > 2. Alors d(log n)5 e > 10. Soient r1 , r2 , . . . , rt tous les entiers tels que soit ri |n soit σri (n) ≤ (log n)2 . Chacun de ces nombres divise le produit : n)2 b(log Y c P =n (ni − 1), i=1 en effet, soit ri |n et alors c’est clair, soit k = σri (n) ≤ (log n)2 , et on a alors nk − 1 ≡ 0 (mod ri ). On a de plus : 4 5 P < n(log n) ≤ 2(log n) ≤ LCM(d(log 5)n e). Il existe donc un entier s ≤ d(log n)5 e tel que s 6∈ {r1 , r2 , . . . , rt }. – Si gcd(s, n) = 1, alors σs (n) > (log n)2 ; s est le témoin d’AKS de n. 30 – Si gcd(s, n) > 1, alors puisque s ne divise pas n et que gcd(s, n) ∈ {r1 , r2 , . . . , rt }, posons : s 6∈ {r1 , r2 , . . . , rt } . r= gcd(s, n) Et alors σr (n) > (log n)2 ; r est le témoin d’AKS de n. 5.3 Complexité de l’algorithme Proposition 5.2 L’algorithme d’Agrawa Kayal et Saxena est de complexité O˜((log n)21/2 ) Démonstration : Elle va s’effectuer en plusieurs étapes. Etape 1 Verifier que n n’est pas une puissance de nombre premier prend un temps en O˜((log n)3 ). Preuve :Pour ce faire on utilise un algorithme de dichotomie : Pour tout entier k tel que 2k ≤ n on teste que n est une puissance k-ième en utilisant deux réferences min et max initialisées respectivement à 0 et n. Si ( min +2 max )k ≤ n, alors on pose min = min +2 max , sinon on pose max = min +2 max . Si mink = n ou maxk = n, alors n est une puissance k-ième. Si |max − min| ≤ 1 et mink 6= n et maxk 6= n, alors n n’est pas une puissance k-ième. Il y a O(log n) entiers k à tester. Pour chaque k, il faut effectuer des calculs de la forme ak où a ≤ n ; pour ce faire, en utilisant l’algorithme d’exponentiation rapide, cela nécessite O(2 log log n) multiplications, chacune de temps O((log n)2 ). La complexité totale est donc : O(2 log log n ∗ (log n)3 ) = O˜((log n)3 ). Etape 2 Trouver le plus petit témoin d’AKS r prend un temps en O˜((log n)7 ). Preuve : Pour trouver un tel entier r, on peut essayer des valeurs successives de r et tester si nk 6≡ 1 (mod r) pour tout k ≤ (log n)2 . Pour un entier r fixé, cette vérification nécessite O((log n)2 ) multiplications modulaires, chacune de temps O((log r)2 ). De plus d’après l’étude précédente faite sur le témoin d’AKS, on sait que r < d(log n)5 e. Il y a donc O((log n)5 ) entiers r à tester. La complexité totale est donc : O((log n)7 ∗ (log r)2 ) = O((log n)7 ∗ (log (log n)5 )2 ) = O˜((log n)7 ). Etape 3 Verifier le troisième point prend un temps en O((log n)8 ). Preuve : Il y a au plus O((log n)5 ) entiers a à tester. Pour chaque entier a fixé, calculer gcd(a, n) prend un temps en O((log n)3 ). La complexité totale est donc O((log n)8 ). Etape 4 Le dernier point de l’algorithme est de complexité O˜((log n)21/2 ). 31 p Preuve : Il y a O( ϕ(r) log n) équations à tester : Pour un entier a fixé, il faut calculer (X + a)n − (X n + a) (mod X r − 1, n). Chaque équation requiert O(log n) multiplications de polynômes de degré r avec des coefficients de taille O(log n). Donc chaque équation est vérifiée en un temps O˜(r(log n)2 ). Ainsi, la complexité totale de cette étape est : p O˜( ϕ(r)r(log n)3 ) = O˜(r3/2 (log n)3 ) = O˜((log n)21/2 ). C’est la complexité de cette dernière étape qui domine toutes les autres ; c’est donc la complexité de l’algorithme. 5.4 Amélioration espérée Conjecture 5.1 Si r est un nombre premier ne divisant pas n ; et si (X − 1)n ≡ X n − 1 (mod X r − 1, n), alors soit n est premier, soit n2 ≡ 1 (mod r) . Si cette conjecture est vérifiée, on peut modifier l’algorithme pour obtenir une complexité en O˜((log n)3 ). En effet, on doit tout d’abord trouver un entier r premier ne divisant pas n2 − 1 et n. Un tel entier devrait se trouver dans l’intervalle [2, 4 log n]. Il ne reste plus alors qu’à vérifier la congruence, qui prend un temps en O˜(r(log n)2 ) ; d’où la complexité totale. 6 Démonstration du déterminisme de cet algorithme Théorème 6.1 théorème d’Agrawal, Kayal et Saxena : Soit n un entier non nul. Le test d’Agrawal, Kayal et Saxena retourne ”n est premier” si et seulement si n est premier. Démonstration : Elle va se faire à l’aide de plusieurs lemmes et propositions successifs : Proposition 6.2 Si n est premier, alors l’algorithme retourne ”n est premier”. Démonstration : Si n est premier, le premier point ne peut jamais retourner ”n est composé” : n ne peut être une puissance. De plus tout entier a est soit premier avec n, soit un multiple de n, donc le troisième point n’est jamais vérifiée. D’après l’étude préliminaire, on a vu que pour n entier premier, on a pour tout entier a et r la relation : (X + a)n ≡ X n + a (mod X r − 1, n). La condition dans la boucle n’est donc là non plus, jamais remplie. L’algorithme ne peut donc identifier n que comme étant un nombre premier (soit parce que n ≤ r soit parce qu’il ne peut rien faire d’autre, étant arrivé à la fin de l’algorithme). La réciproque demande un peu plus de travail et nécessite une étude approfondie supplémentaire. 32 Lemme 6.1 Si l’algorithme répond ”n est premier” au quatrième point, alors n est premier. Preuve : Si l’algorithme sort à ce moment, c’est que n n’est pas une puissance, et que de plus n vérifie : gcd(a, n) = 1 ou gcd(a, n) = n pour tout a ≤ r. En particulier, puisque n < r : gcd(a, n) = 1 pour tout a < n. Ce qui implique que n est un nombre premier. Remarquons que si l’on a n ≤ r alors n ≤ (log n)5 , ce qui ne peut arriver que si n ≤ 5 690 034. Proposition 6.3 Si l’algorithme affirme ”n est premier” au dernier point, alors n est premier. Démonstration : Si l’algorithme affirme que n est premier après le dernier point, alors cela implique en particulier que : – n n’est pas une puissance. – r<n – Pour tout entier a ≤ r, a n est premier avec n. jp ko – Pour tout entier a ∈ S = 0, 1, . . . , ϕ(r) log n on a : (X + a)n ≡ X n + a (mod X r − 1, n). jp k Posons s = ϕ(r) log n . Supposons que n est composé. Puisque σr (n) > 1, il existe un diviseur premier p de n tel que σr (p) > 1. De plus p > r, car sinon pour a = p, gcd(a, n) = p < n, ce qui entre en contradiction avec les affirmations précédentes. On a donc les relations : (X+a)n ≡ X n +a (mod X r −1, p) et puisque p est premier (X+a)p ≡ X p +a L’idée est de combiner ces deux relations pour arriver à une contradiction. Lemme 6.2 Soient m1 et m2 deux entiers. Si (X + a)m1 ≡ X m1 + a (mod X r − 1, p) et (X + a)m2 ≡ X m2 + a (mod X r − 1, p), alors (X + a)m1 m2 ≡ X m1 m2 + a 33 (mod X r − 1, p). (mod X r −1, p). Preuve : Il existe g(X) ∈ Fp [X] tel que (X + a)m2 − X m2 − a = (X r − 1)g(X). D’où (X m1 + a)m2 − X m1 m2 + a = (X m1 r − 1)g(X m1 ). Et (X r − 1) |(X m1 r − 1) (car (X − 1) |(X m1 − 1)), donc : (X + a)m1 m2 ≡ (X m1 + a)m2 ≡ X m1 m2 + a (mod X r − 1, p). On en déduit ainsi que pour tout entier positif i,j et pour tout a ∈ S on a la relation : i j i j (X + a)p n ≡ X p n + a (mod X r − 1, p). √ Posons L = {pi nj | 0 ≤ i, j ≤ b rc}. Comme n n’est pas une puissance de nombre premier,tous les éléments de L sont distincts. √ 2 Ainsi l’ensemble L a (b rc + 1) > r éléments. Donc √ deux éléments de L sont congrus modulo r. Soit m1 et m2 deux tels nombres avec b nc ≥ m1 ≥ m2 : m1 = pi1 nj1 ≡ pi2 nj2 = m1 + kr = m2 pour (i1 , j1 ) 6= (i2 , j2 ). Et donc on a : (X)m2 ≡ X m1 +kr ≡ X m1 ≡ (X)m1 (mod X r − 1). Si on montre à présent que m1 = m2 , alors on aura montré que n = pt , ce qui contredira l’hypothèse initiale. Pour cela, on va montrer que le polynôme R(Y ) = Y m1 − Y m2 est identiquement nul, en exhibant un ensemble de racines de cardinal supérieur au degré de R. Définissons deux groupes qui vont nous être utiles pour la suite de la démonstration. Le premier est le sous groupe G de (Z/rZ)∗ généré par n (mod r) et p (mod r). Posons |G| = t, et puisque σr (n) > (log n)2 , t > (log n)2 . Pour le second, choisissons un facteur irréductible du r-ième polynôme cyclotomique de Fp [X], soit h(X). Le degré d de h est alors d = σp r. Considérons le corps fini A = Fp [X]/(h(X)), à pd éléments ; et posons ξ = X (mod h(X), p). Soit à présent le groupe G, engendré par les ξ + a, pour a ∈ S ; c’est un sous groupe de A∗ . √ Lemme 6.3 |G| > n t t−1 Preuve : On va d’abord montrer que |G| > Ct+s : Soit l’ensemble P definit par : ( ) Y P = (X + a)ea | ea ≥ 0 , a∈S et soit Q sous ensemble de P formé par les produits : Y X (X + a)αa avec αa ≤ t − 1 et αa ≥ 0. a∈S a∈S 34 Remarquons que ξ est une racine primitive r-ième de l’unité dans A en effet le polynôme X r − 1 est divisible par h(X) : si l’on substitue ξ à X dans X r − 1 ≡ 0 (mod h(X)), on obtient ξ r = 1 dans A. Montrons à présent que pour tout f , g polynômes de Q, si f (ξ) = g(ξ) dans A, alors f (X) = g(X). Soit m ∈ G. On a alors : f (ξ)m = g(ξ)m dans A. Et d’après le lemme précédent, et puisque h(X) divise X r − 1, on a : f (ξ m ) = g(ξ m ) dans A. Ce qui implique que ξ m est une racine du polynôme non nul R0 (Y ) = f (Y ) − g(Y ) pour tout m ∈ G. Puisque m est premier avec r(car G est un sous groupe de (Z/rZ)∗ ), chaque ξ m est une racine r-ième de l’unité. Donc il y a |G| = t racines distinctes du polynôme R0 . Cependant le degré de R0 est plus petit que t par le choix de f et g, ce qui implique donc que R0 est le polynôme identiquement nul. Remarquons que les éléments ξ, ξ + 1, . . . , ξ + s sont tous distincts dans A. En effet : jp k √ s= ϕ(r) log n < r log n < r et p > r. Donc puisque le degré de h est superieur à 1, ξ + a 6= 0 dans A pour tout a, 0 ≤ a ≤ s. t−1 Il existe donc s + 1 polynômes distincts de degré 1 dans G, et donc il existe Ct+s polynômes distincts de degré plus petit que t dans G. On a donc : et puisque t > √ t−1 |G| ≥ Ct+s t log n, b √ t log nc √ b t log nc |G| ≥ Cs+1+ or s = jp k √ ϕ(r) log n ≥ t log n , donc √ b t log nc |G| ≥ C2 √t log n +1 c b de plus √ t log n > b(log n)2 c donc |G| > 2b √ t log nc+1 et ainsi, √ |G| > n t . Soit à présent f (X) un élément de P ; alors [f (X)]m1 ≡ f (X m1 ) ≡ f (X m2 ) ≡ [f (X)]m2 35 (mod X r − 1, p); ce qui implique donc que f (ξ)m1 = f (ξ)m2 . Donc f (ξ) ∈ G est une racine du polynôme R(Y ) = Y m1 − Y m−2 dans le corps A. Puisque f (ξ) est un élément arbitraire de G, le polynôme R(Y ) a au moins |G|, soit plus √ t de n racines distinctes. R(Y ) est donc le polynôme nul, en particulier, m1 = m2 et donc n est une puissance de nombre premier , donc n = p (d’après les hypothèses initiales) et est ainsi premier. Conclusion On comprend à présent l’importance de la course aux nombres premiers : cette recherche, gymnastique de l’esprit au début est devenue avec l’essor de la cryptographie une véritable course au trésor, chaque nouveau nombre premier se vendant à prix d’or. Cette recherche évolue en deux directions : la première s’effectue à l’aide d’ordinateurs que des gens n’hésitent pas à faire tourner des mois et des mois pour trouver un nouveau nombre. La seconde se tourne vers l’algorithmique ; l’algorithme d’Agrawal Kayal et Saxena en étant la dernière preuve. Cependant cet algorithme bien que très innovant, au sens où il est le premier à avoir une complexité polynomiale, a néanmoins le défaut non négligeable d’avoir une portée pratique très limité : en effet, les algorithmes classiques de primalité tels que le test de Miller-Rabin sont beaucoup plus rapides pour les entiers que l’on peut tester avec la puissance actuelle de nos ordinateurs. Hélas ces algorithmes sont probabilistes et ne nous donnent donc que des nombres probablement premiers. De nos jours, il n’est ainsi pas rare d’utiliser des nombres premiers avec une probabilité de 999 pour 1000 par exemple. Il reste donc encore beaucoup de travail dans le domaine de la théorie des nombres pour mettre à bas ces difficultés. Belle revanche pour cette théorie, trop souvent incriminée d’inutilité. 36 Références [1] Agrawal M. ; Kayal N. ; Saxena N. : www.cse.iitk.ac.in/user/manindra : Primes is in P [2] Bornemann Folkmar : Primes is in P, une avancée accessible à « l’homme ordinaire » [3] Collection Mathémathemes : Les nombres : Problèmes anciens et actuels [4] Crandall Richard ; Pomerance Carl : Prime Number : A computational perspective [5] Delahaye Jean-Paul : Merveilleux nombres premiers : voyage au cœur de l’arithmétique [6] Duminil Hugo : RMS, 116ème année, Mai 2004, no 4 : Tests de primalité : « Primes is in P » [7] Everest Grahan ; Word Thomas : An Introduction to Number Theory [8] Gardner Martin : Les Distracts : Jeux mathématiques du ”Scientific American” [9] Hindry : www.math.jussieu.fr/∼hindry/cours-arith.pdf : Cours d’arithmétique [10] Louboutin : www.lumimath.univ-mrs.fr/coursL2/mat2LOUBOUTIN.pdf : Cours d’arithmétique [11] Maurras Jean-François : Programmation Linéaire, Compexité : Séparation et Optimisation [12] Mignotte Maurice : Mathématiques pour le calcul formel [13] Morain F. : Seminaire Bourbaki, 55ème année, Mars 2003 no 917 : La primalité en temps polynomial [14] Ribenboim Paulo : Nombres premiers : mystères et records 37 [15] Rose H.E. : A course in number Theory [16] Schneier Bruce : Cryptographie appliquée [17] Singh Simon : Histoires des codes secrets : de l’Egypte des Pharaons à l’ordinateur quantique [18] Stahl Saul : Introductory Modern Algebra : A historical approash [19] Stinson Douglas : Cryptographie : théorie et pratique [20] Zémor Gilles : Cours de cryptographie [21] Wikipedia : www.wikipedia.org : théorie de la complexité [22] Wilf H.S : Algorithme et complexité 38