Skip to content

Commit 8bdb02e

Browse files
committed
Merge branch 'lucas'
2 parents f64df6f + 66fdb1f commit 8bdb02e

File tree

4 files changed

+42
-14
lines changed

4 files changed

+42
-14
lines changed

Changelog.rst

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Changelog
22
=========
33

4+
3.6.5 (xx xxxxx 2018)
5+
+++++++++++++++++++++
6+
7+
Resolved issues
8+
---------------
9+
10+
* GH#188: In the Lucas probable prime test, do an exhaustive search for D values,
11+
as opposed to trying only the first few.
12+
413
3.6.4 (10 July 2018)
514
+++++++++++++++++++++
615

lib/Crypto/Math/Primality.py

+19-9
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ def miller_rabin_test(candidate, iterations, randfunc=None):
6363
if not isinstance(candidate, Integer):
6464
candidate = Integer(candidate)
6565

66+
if candidate in (1, 2, 3, 5):
67+
return PROBABLY_PRIME
68+
6669
if candidate.is_even():
6770
return COMPOSITE
6871

@@ -129,25 +132,30 @@ def lucas_test(candidate):
129132
candidate = Integer(candidate)
130133

131134
# Step 1
135+
if candidate in (1, 2, 3, 5):
136+
return PROBABLY_PRIME
132137
if candidate.is_even() or candidate.is_perfect_square():
133138
return COMPOSITE
134139

135140
# Step 2
136141
def alternate():
137-
sgn = 1
138142
value = 5
139-
for x in xrange(20):
140-
yield sgn * value
141-
sgn, value = -sgn, value + 2
143+
while True:
144+
yield value
145+
if value > 0:
146+
value += 2
147+
else:
148+
value -= 2
149+
value = -value
142150

143151
for D in alternate():
152+
if candidate in (D, -D):
153+
continue
144154
js = Integer.jacobi_symbol(D, candidate)
145155
if js == 0:
146156
return COMPOSITE
147157
if js == -1:
148158
break
149-
else:
150-
return COMPOSITE
151159
# Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer)
152160

153161
# Step 3
@@ -205,7 +213,7 @@ def alternate():
205213
from Crypto.Util.number import sieve_base as _sieve_base
206214
## The optimal number of small primes to use for the sieve
207215
## is probably dependent on the platform and the candidate size
208-
_sieve_base = _sieve_base[:100]
216+
_sieve_base = set(_sieve_base[:100])
209217

210218

211219
def test_probable_prime(candidate, randfunc=None):
@@ -236,11 +244,13 @@ def test_probable_prime(candidate, randfunc=None):
236244
if not isinstance(candidate, Integer):
237245
candidate = Integer(candidate)
238246

239-
# First, check trial division by the smallest primes
247+
# First, check trial division by the smallest primes
248+
if int(candidate) in _sieve_base:
249+
return PROBABLY_PRIME
240250
try:
241251
map(candidate.fail_if_divisible_by, _sieve_base)
242252
except ValueError:
243-
return False
253+
return COMPOSITE
244254

245255
# These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30,
246256
# with p(k, t) being the probability that a randomly chosen k-bit number

lib/Crypto/SelfTest/Math/test_Primality.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,24 @@
5151

5252
class TestPrimality(unittest.TestCase):
5353

54-
primes = (13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539)
55-
composites = (12, 7*23, (2**19-1)*(2**67-1), 9746347772161,)
54+
primes = (1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539)
55+
composites = (0, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 7*23, (2**19-1)*(2**67-1), 9746347772161,)
5656

5757
def test_miller_rabin(self):
5858
for prime in self.primes:
5959
self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME)
6060
for composite in self.composites:
6161
self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE)
62+
self.assertRaises(ValueError, miller_rabin_test, -1, 3)
6263

6364
def test_lucas(self):
6465
for prime in self.primes:
65-
self.assertEqual(lucas_test(prime), PROBABLY_PRIME)
66+
res = lucas_test(prime)
67+
self.assertEqual(res, PROBABLY_PRIME)
6668
for composite in self.composites:
67-
self.assertEqual(lucas_test(composite), COMPOSITE)
69+
res = lucas_test(composite)
70+
self.assertEqual(res, COMPOSITE)
71+
self.assertRaises(ValueError, lucas_test, -1)
6872

6973
def test_is_prime(self):
7074
primes = (170141183460469231731687303715884105727,
@@ -82,6 +86,11 @@ def test_is_prime(self):
8286
for np in not_primes:
8387
self.assertEqual(test_probable_prime(np), COMPOSITE)
8488

89+
from Crypto.Util.number import sieve_base
90+
for p in sieve_base[:100]:
91+
res = test_probable_prime(p)
92+
self.assertEqual(res, PROBABLY_PRIME)
93+
8594
def test_generate_prime_bit_size(self):
8695
p = generate_probable_prime(exact_bits=512)
8796
self.assertEqual(p.size_in_bits(), 512)

lib/Crypto/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature',
22
'IO', 'Math']
33

4-
version_info = (3, 6, 4)
4+
version_info = (3, 6, 5, "a0")
55

66
__version__ = ".".join([str(x) for x in version_info])

0 commit comments

Comments
 (0)