1# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Tests prime functions.""" 16 17import unittest 18 19import rsa.prime 20import rsa.randnum 21 22 23class PrimeTest(unittest.TestCase): 24 def test_is_prime(self): 25 """Test some common primes.""" 26 27 # Test some trivial numbers 28 self.assertFalse(rsa.prime.is_prime(-1)) 29 self.assertFalse(rsa.prime.is_prime(0)) 30 self.assertFalse(rsa.prime.is_prime(1)) 31 self.assertTrue(rsa.prime.is_prime(2)) 32 self.assertFalse(rsa.prime.is_prime(42)) 33 self.assertTrue(rsa.prime.is_prime(41)) 34 35 # Test some slightly larger numbers 36 self.assertEqual( 37 [907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997], 38 [x for x in range(901, 1000) if rsa.prime.is_prime(x)] 39 ) 40 41 # Test around the 50th millionth known prime. 42 self.assertTrue(rsa.prime.is_prime(982451653)) 43 self.assertFalse(rsa.prime.is_prime(982451653 * 961748941)) 44 45 def test_miller_rabin_primality_testing(self): 46 """Uses monkeypatching to ensure certain random numbers. 47 48 This allows us to predict/control the code path. 49 """ 50 51 randints = [] 52 53 def fake_randint(maxvalue): 54 return randints.pop(0) 55 56 orig_randint = rsa.randnum.randint 57 rsa.randnum.randint = fake_randint 58 try: 59 # 'n is composite' 60 randints.append(2630484832) # causes the 'n is composite' case with n=3784949785 61 self.assertEqual(False, rsa.prime.miller_rabin_primality_testing(2787998641, 7)) 62 self.assertEqual([], randints) 63 64 # 'Exit inner loop and continue with next witness' 65 randints.extend([ 66 2119139098, # causes 'Exit inner loop and continue with next witness' 67 # the next witnesses for the above case: 68 3051067716, 3603501763, 3230895847, 3687808133, 3760099987, 4026931495, 3022471882, 69 ]) 70 self.assertEqual(True, rsa.prime.miller_rabin_primality_testing(2211417913, 71 len(randints))) 72 self.assertEqual([], randints) 73 finally: 74 rsa.randnum.randint = orig_randint 75 76 def test_mersenne_primes(self): 77 """Tests first known Mersenne primes. 78 79 Mersenne primes are prime numbers that can be written in the form 80 `Mn = 2**n - 1` for some integer `n`. For the list of known Mersenne 81 primes, see: 82 https://en.wikipedia.org/wiki/Mersenne_prime#List_of_known_Mersenne_primes 83 """ 84 85 # List of known Mersenne exponents. 86 known_mersenne_exponents = [ 87 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 88 2203, 2281, 4423, 89 ] 90 91 # Test Mersenne primes. 92 for exp in known_mersenne_exponents: 93 self.assertTrue(rsa.prime.is_prime(2**exp - 1)) 94 95 def test_get_primality_testing_rounds(self): 96 """Test round calculation for primality testing.""" 97 98 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 63), 10) 99 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 127), 10) 100 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 255), 10) 101 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 511), 7) 102 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 767), 7) 103 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 1023), 4) 104 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 1279), 4) 105 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 1535), 3) 106 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 2047), 3) 107 self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 4095), 3) 108