La méthode BigInteger.isProbablePrime()
est assez étrange; à partir de la documentation, cela indiquera si un nombre est premier avec une probabilité de 1 - 1 / 2^arg
, où arg
est l'argument entier.
Il est présent dans le JDK depuis assez longtemps, cela signifie donc qu'il doit avoir des utilisations. Mes connaissances limitées en informatique et en algorithmes (et mathématiques) me disent que cela n'a pas vraiment de sens de savoir si un nombre est "probablement" un nombre premier mais pas exactement un nombre premier.
Alors, quel est un scénario possible où l'on voudrait utiliser cette méthode? Cryptographie?
Oui, cette méthode peut être utilisée en cryptographie. chiffrement RSA implique la recherche d'énormes nombres premiers, parfois de l'ordre de 1024 bits (environ 300 chiffres). La sécurité de RSA dépend du fait que la factorisation d'un nombre composé de 2 de ces nombres premiers multipliés ensemble est extrêmement difficile et prend du temps. Mais pour que cela fonctionne, ils doivent être primordiaux.
Il s'avère que prouver ces nombres premiers est également difficile. Mais le test de primalité de Miller-Rabin , l'un des tests de primalité utilisé par isProbablePrime
, détecte qu'un nombre est composite ou ne donne aucune conclusion. L'exécution de ce test n
fois vous permet de conclure qu'il y a un 1 sur 2n il y a de fortes chances que ce nombre soit vraiment composite. L'exécution 100
fois donne le risque acceptable de 1 sur 2100 que ce nombre est composite.
Si le test vous indique qu'un entier est pas premier, vous pouvez certainement le croire à 100%.
Ce n'est que de l'autre côté de la question, si le test vous indique qu'un entier est "un nombre probable probable", que vous pouvez entretenir le doute. La répétition du test avec différentes "bases" permet de rendre aussi faible que possible la probabilité de réussir à "imiter" un premier (étant un pseudo-premier fort par rapport à plusieurs bases).
L'utilité du test réside dans sa rapidité et sa simplicité. On ne serait pas nécessairement satisfait du statut de "prime probable" comme réponse finale, mais on éviterait certainement de perdre du temps sur presque tous les nombres composites en en utilisant cette routine avant de faire entrer les gros canons des tests de primalité .
La comparaison avec la difficulté de factoriser des entiers est quelque chose d'un hareng rouge. On sait que la primauté d'un entier peut être déterminée en temps polynomial, et en effet il existe une preuve qu'une extension du test de Miller-Rabin à suffisamment de bases est définitive (dans la détection des nombres premiers, par opposition aux nombres premiers probables), mais cela suppose l'hypothèse de Riemann généralisée, il n'est donc pas aussi certain que le (plus cher) test de primalité AKS .
Le cas d'utilisation standard pour BigInteger.isProbablePrime(int)
est en cryptographie. Plus précisément, certains algorithmes cryptographiques, tels que RSA , nécessitent de grands nombres premiers choisis au hasard. Mais surtout, ces algorithmes n'exigent pas vraiment que ces nombres soient garantis pour être premiers - ils ont juste besoin d'être premiers avec une probabilité élevée très.
Quelle hauteur est très élevée? Eh bien, dans une application de chiffrement, on appelle généralement .isProbablePrime()
avec un argument quelque part entre 128 et 256. Ainsi, la probabilité qu'un nombre non premier passe un tel test est inférieure à un sur 2128 ou 2256.
Mettons cela en perspective: si vous aviez 10 milliards d'ordinateurs, chacun générant 10 milliards de nombres premiers probables par seconde (ce qui signifierait moins d'un cycle d'horloge par nombre sur n'importe quel processeur moderne), et la primauté de ces nombres a été testée avec .isProbablePrime(128)
, vous vous attendriez, en moyenne, à ce qu'un nombre non premier entre une fois tous les 100 milliards d'années .
C'est-à-dire que ce serait le cas si ces 10 milliards d'ordinateurs pouvaient en quelque sorte fonctionner pendant des centaines de milliards d'années sans subir de pannes matérielles any. En pratique, cependant , il est beaucoup plus probable qu'un rayon cosmique aléatoire frappe votre ordinateur au bon moment et au bon endroit pour inverser la valeur de retour de .isProbablePrime(128)
de faux à vrai, sans provoquer d'autres effets détectables, qu'il ne l'est pour un nombre non premier de passer réellement le test de primalité probabiliste à ce niveau de certitude.
Bien sûr, le même risque de rayons cosmiques aléatoires et d'autres défauts matériels s'applique également aux tests de primalité déterministes comme AKS . Ainsi, dans la pratique, même ces tests ont un taux de faux positifs de base (très faible) dû à des pannes matérielles aléatoires (sans parler de toutes les autres sources possibles d'erreurs, comme les bogues d'implémentation).
Puisqu'il est facile de pousser le taux intrinsèque de faux positifs du test de primalité de Miller-Rabin utilisé par .isProbablePrime()
bien en dessous de ce taux de base, simplement en répétant le test suffisamment de fois, et puisque , même répété tant de fois, le test de Miller-Rabin est encore beaucoup plus rapide dans la pratique que les meilleurs tests de primalité déterministe comme AKS, il reste le test de primalité standard pour les applications cryptographiques.
(En outre, même s'il vous arrivait de sélectionner accidentellement un pseudoprime fort comme l'un des facteurs de votre module RSA, cela n'entraînerait généralement pas une défaillance catastrophique. En général, ces pseudoprimes seraient le produit de deux (ou rarement plus) nombres premiers d'environ la moitié de la longueur, ce qui signifie que vous vous retrouveriez avec une clé RSA multi-prime . Tant qu'aucun des facteurs n'était aussi petit (et s'ils étaient, le test de primalité aurait dû les détecter), l'algorithme RSA fonctionnera toujours très bien, et la clé, bien que légèrement plus faible contre certains types d'attaques que les clés RSA normales de même longueur, devrait toujours être raisonnablement sécurisée si vous ne l'avez pas fait ne lésinez pas inutilement sur la longueur de la clé.)
Un cas d'utilisation possible consiste à tester la primalité d'un nombre donné (à un test qui en soi a de nombreuses utilisations). L'algorithme isProbablePrime
fonctionnera beaucoup plus rapidement qu'un algorithme exact, donc si le nombre échoue isProbablePrime
, alors il n'est pas nécessaire de faire les frais de l'exécution de l'algorithme plus cher.
Trouver nombres premiers probables est un problème important en cryptographie. Il s'avère qu'une stratégie raisonnable pour trouver un nombre probable de k bits consiste à sélectionner à plusieurs reprises un nombre aléatoire de k bits et à le tester pour la primalité probable en utilisant une méthode comme isProbablePrime()
.
Pour plus de détails, voir section 4.4.1 du Handbook of Applied Cryptography .
Voir aussi Sur la génération de nombres probables probables par recherche incrémentale par Brandt et Damgård.
Des algorithmes tels que la génération de clés RSA reposent sur la possibilité de déterminer si un nombre est premier ou non.
Cependant, au moment où la méthode isProbablePrime
a été ajoutée au JDK (février 1997), il n'existait aucun moyen éprouvé de déterminer de manière déterministe si un nombre était premier dans un délai raisonnable. L'approche la plus connue à l'époque était le algorithme de Miller-Rabin - un algorithme probabiliste qui donnerait parfois des faux positifs (c.-à-d., Rapporterait les non-nombres premiers comme des nombres premiers), mais pourrait être réglé pour réduire la probabilité de faux positifs, au prix d'une augmentation modeste de la durée d'exécution.
Depuis lors, des algorithmes ont été découverts qui peuvent déterminer de manière déterministe si un nombre est premier assez rapidement, comme le algorithme AKS découvert en août 2002. Cependant, il convient de noter que ces algorithmes ne sont toujours pas aussi vite que Miller-Rabin.
Une meilleure question est peut-être de savoir pourquoi aucune méthode isPrime
n'a été ajoutée au JDK depuis 2002.