From 66fdb1fdd437669513d9ad0095f8023950a8421d Mon Sep 17 00:00:00 2001 From: Helder Eijs Date: Thu, 9 Aug 2018 22:48:24 +0200 Subject: [PATCH] Increase testing for primality --- lib/Crypto/Math/Primality.py | 15 ++++++++++++--- lib/Crypto/SelfTest/Math/test_Primality.py | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/Crypto/Math/Primality.py b/lib/Crypto/Math/Primality.py index 74e4d5454..8ae0f61f5 100644 --- a/lib/Crypto/Math/Primality.py +++ b/lib/Crypto/Math/Primality.py @@ -63,6 +63,9 @@ def miller_rabin_test(candidate, iterations, randfunc=None): if not isinstance(candidate, Integer): candidate = Integer(candidate) + if candidate in (1, 2, 3, 5): + return PROBABLY_PRIME + if candidate.is_even(): return COMPOSITE @@ -129,6 +132,8 @@ def lucas_test(candidate): candidate = Integer(candidate) # Step 1 + if candidate in (1, 2, 3, 5): + return PROBABLY_PRIME if candidate.is_even() or candidate.is_perfect_square(): return COMPOSITE @@ -144,6 +149,8 @@ def alternate(): value = -value for D in alternate(): + if candidate in (D, -D): + continue js = Integer.jacobi_symbol(D, candidate) if js == 0: return COMPOSITE @@ -206,7 +213,7 @@ def alternate(): from Crypto.Util.number import sieve_base as _sieve_base ## The optimal number of small primes to use for the sieve ## is probably dependent on the platform and the candidate size -_sieve_base = _sieve_base[:100] +_sieve_base = set(_sieve_base[:100]) def test_probable_prime(candidate, randfunc=None): @@ -237,11 +244,13 @@ def test_probable_prime(candidate, randfunc=None): if not isinstance(candidate, Integer): candidate = Integer(candidate) - # First, check trial division by the smallest primes + # First, check trial division by the smallest primes + if int(candidate) in _sieve_base: + return PROBABLY_PRIME try: map(candidate.fail_if_divisible_by, _sieve_base) except ValueError: - return False + return COMPOSITE # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, # with p(k, t) being the probability that a randomly chosen k-bit number diff --git a/lib/Crypto/SelfTest/Math/test_Primality.py b/lib/Crypto/SelfTest/Math/test_Primality.py index f89e1bf65..85297b3f5 100644 --- a/lib/Crypto/SelfTest/Math/test_Primality.py +++ b/lib/Crypto/SelfTest/Math/test_Primality.py @@ -51,20 +51,24 @@ class TestPrimality(unittest.TestCase): - primes = (13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539) - composites = (12, 7*23, (2**19-1)*(2**67-1), 9746347772161,) + primes = (1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539) + composites = (0, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 7*23, (2**19-1)*(2**67-1), 9746347772161,) def test_miller_rabin(self): for prime in self.primes: self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME) for composite in self.composites: self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE) + self.assertRaises(ValueError, miller_rabin_test, -1, 3) def test_lucas(self): for prime in self.primes: - self.assertEqual(lucas_test(prime), PROBABLY_PRIME) + res = lucas_test(prime) + self.assertEqual(res, PROBABLY_PRIME) for composite in self.composites: - self.assertEqual(lucas_test(composite), COMPOSITE) + res = lucas_test(composite) + self.assertEqual(res, COMPOSITE) + self.assertRaises(ValueError, lucas_test, -1) def test_is_prime(self): primes = (170141183460469231731687303715884105727, @@ -82,6 +86,11 @@ def test_is_prime(self): for np in not_primes: self.assertEqual(test_probable_prime(np), COMPOSITE) + from Crypto.Util.number import sieve_base + for p in sieve_base[:100]: + res = test_probable_prime(p) + self.assertEqual(res, PROBABLY_PRIME) + def test_generate_prime_bit_size(self): p = generate_probable_prime(exact_bits=512) self.assertEqual(p.size_in_bits(), 512)