Standardowy przypadek użycia BigInteger.isProbablePrime(int)
to kryptografia. W szczególności niektóre algorytmy kryptograficzne, takie jak RSA , wymagają losowo wybranych dużych liczb pierwszych. Jednak co ważne, te algorytmy nie wymagają, aby te liczby były gwarantowane jako pierwsze - po prostu muszą być liczbami pierwszymi z bardzo dużym prawdopodobieństwem.
Jak wysoko jest bardzo wysoko? Cóż, w aplikacji kryptograficznej zwykle dzwoniłoby się .isProbablePrime()
z argumentem między 128 a 256. Zatem prawdopodobieństwo, że liczba inna niż pierwsza przejdzie taki test jest mniejsze niż jeden na 2 128 lub 2 256 .
Spójrzmy na to z perspektywy: gdybyś miał 10 miliardów komputerów, z których każdy generował 10 miliardów prawdopodobnych liczb pierwszych na sekundę (co oznaczałoby mniej niż jeden cykl zegara na liczbę na dowolnym nowoczesnym procesorze), a pierwotność tych liczb została przetestowana .isProbablePrime(128)
na spodziewałby się, że jedna liczba inna niż pierwsza pojawi się raz na 100 miliardów lat .
To znaczy, że tak by było, gdyby te 10 miliardów komputerów mogło w jakiś sposób działać przez setki miliardów lat bez żadnych awarii sprzętu. W praktyce jednak, jest to dużo bardziej prawdopodobne w przypadku losowego promieniowania kosmicznego uderzyć komputer w odpowiednim czasie i miejscu, aby odwrócić wartości zwracanej z .isProbablePrime(128)
z false na true, nie powodując żadnych innych efektów wykrywalne, niż jest to dla nie -liczba pierwsza, która faktycznie przejdzie probabilistyczny test pierwszości na tym poziomie pewności.
Oczywiście to samo ryzyko przypadkowych promieni kosmicznych i innych usterek sprzętowych dotyczy również deterministycznych testów pierwszości, takich jak AKS . Dlatego w praktyce nawet te testy mają (bardzo mały) podstawowy wskaźnik fałszywie pozytywnych wyników z powodu przypadkowych awarii sprzętu (nie wspominając o wszystkich innych możliwych źródłach błędów, takich jak błędy implementacji).
Ponieważ łatwo jest przesunąć wewnętrzny odsetek fałszywie dodatnich wyników testu pierwszości Millera – Rabina, stosowanego .isProbablePrime()
znacznie poniżej tego wskaźnika podstawowego, po prostu powtarzając test dostatecznie wiele razy, a ponieważ, nawet powtarzany tak wiele razy, test Millera – Rabina jest nadal znacznie szybszy w praktyce niż najbardziej znane deterministyczne testy pierwszości, takie jak AKS, pozostaje standardowym testem pierwszości dla aplikacji kryptograficznych.
(Poza tym, nawet jeśli przypadkowo wybrałeś silną liczbę pseudopierwszą jako jeden z czynników twojego modułu RSA, generalnie nie doprowadziłoby to do katastrofalnej awarii. Zazwyczaj takie liczby pseudopierwsze byłyby iloczynami dwóch (lub rzadko więcej) liczb pierwszych w przybliżeniu połowę długości, co oznacza, że otrzymasz klucz RSA o wielu liczbach pierwszych . Dopóki żaden z tych czynników nie będzie zbyt mały (a jeśli tak, to test pierwszości powinien je wychwycić), algorytm RSA będzie nadal działa dobrze, a klucz, chociaż nieco słabszy w przypadku niektórych typów ataków niż zwykłe klucze RSA o tej samej długości, powinien być wystarczająco bezpieczny, jeśli nie będziesz niepotrzebnie skąpić na długości klucza.)