Skip to content

Commit

Permalink
Set Miller-Rabin rounds based on bitsize
Browse files Browse the repository at this point in the history
  • Loading branch information
adamantike committed Apr 15, 2016
1 parent 96eaa5e commit 27b4a98
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 8 deletions.
40 changes: 32 additions & 8 deletions rsa/prime.py
Expand Up @@ -20,6 +20,7 @@
Roberto Tamassia, 2002.
"""

import rsa.common
import rsa.randnum

__all__ = ['getprime', 'are_relatively_prime']
Expand All @@ -37,6 +38,32 @@ def gcd(p, q):
return p


def get_primality_testing_rounds(number):
"""Returns minimum number of rounds for Miller-Rabing primality testing,
based on number bitsize.
According to NIST FIPS 186-4, Appendix C, Table C.3, minimum number of
rounds of M-R testing, using an error probability of 2 ** (-100), for
different p, q bitsizes are:
* p, q bitsize: 512; rounds: 7
* p, q bitsize: 1024; rounds: 4
* p, q bitsize: 1536; rounds: 3
See: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
"""

# Calculate number bitsize.
bitsize = rsa.common.bit_size(number)
# Set number of rounds.
if bitsize >= 1536:
return 3
if bitsize >= 1024:
return 4
if bitsize >= 512:
return 7
# For smaller bitsizes, set arbitrary number of rounds.
return 10


def miller_rabin_primality_testing(n, k):
"""Calculates whether n is composite (which is always correct) or prime
(which theoretically is incorrect with error probability 4**-k), by
Expand Down Expand Up @@ -109,14 +136,11 @@ def is_prime(number):
if not (number & 1):
return False

# According to NIST FIPS 186-4, Appendix C, Table C.3, minimum number of
# rounds of M-R testing, using an error probability of 2 ** (-100), for
# different p, q bitsizes are:
# * p, q bitsize: 512; rounds: 7
# * p, q bitsize: 1024; rounds: 4
# * p, q bitsize: 1536; rounds: 3
# See: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
return miller_rabin_primality_testing(number, 7)
# Calculate minimum number of rounds.
k = get_primality_testing_rounds(number)

# Run primality testing with (minimum + 1) rounds.
return miller_rabin_primality_testing(number, k + 1)


def getprime(nbits):
Expand Down
14 changes: 14 additions & 0 deletions tests/test_prime.py
Expand Up @@ -74,3 +74,17 @@ def fake_randint(maxvalue):
self.assertEqual([], randints)
finally:
rsa.randnum.randint = orig_randint

def test_get_primality_testing_rounds(self):
"""Test round calculation for primality testing."""

self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 63), 10)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 127), 10)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 255), 10)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 511), 7)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 767), 7)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 1023), 4)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 1279), 4)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 1535), 3)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 2047), 3)
self.assertEquals(rsa.prime.get_primality_testing_rounds(1 << 4095), 3)

0 comments on commit 27b4a98

Please sign in to comment.