99from functools import reduce
1010from operator import mul
1111from sys import version_info
12- from rsa import newkeys
1312from argparse import ArgumentParser
1413
1514NUMPY_ENABLED = True
2019except ImportError :
2120 NUMPY_ENABLED = False
2221
23- print ()
22+ PRIME_TEST = False
23+ FACTOR_TEST = False
24+ try :
25+ from rsa import newkeys , __version__
26+ print ('Detected rsa version {__version__}' .format (** locals ()))
2427
25- PRIME_TEST = True
26- FACTOR_TEST = True
28+ except ImportError :
29+ FACTOR_TEST = False
2730
2831LEFT = 'left'
2932RIGHT = 'right'
@@ -44,6 +47,21 @@ def _check_num(n):
4447 if n <= 0 :
4548 raise ValueError ('The number of argument n should be greater than 0, got {n}' .format (** locals ()))
4649
50+ def _check_factors (ans , n , retry = 1 , max_retries = 3 ):
51+ '''
52+ Internel function to check the output.
53+ '''
54+ if reduce (mul , ans ) == n :
55+ return 0
56+
57+ if retry == max_retries + 1 :
58+ print (f'Factor Error. The multiplication of { ans } is not { n } .' )
59+ raise FactorError (f'Factor Error. The multiplication of { ans } is not { n } .' )
60+
61+ print (f'Factor Error. The multiplication of { ans } is not { n } . Retry { retry } .' )
62+
63+ return retry + 1
64+
4765def is_prime (n ):
4866 '''
4967 If n is prime, return True.
@@ -2753,14 +2771,14 @@ def mpqsfind(n, s = 0, f = 0, m = 0):
27532771
27542772 X = floorsqrt (X ) % M .number
27552773 if X != Y :
2756- differences .append (X - Y )
2774+ differences .append (X - Y )
27572775
27582776 for diff in differences :
27592777 divisor = gcd (diff , N )
27602778 if 1 < divisor < N :
27612779 return divisor
27622780
2763- def mpqs (n , retry = 1 , max_retries = 3 ):
2781+ def mpqs (n , retry = 1 , min_ = 20 ):
27642782 num = n
27652783 ans = []
27662784 if is_prime (n ):
@@ -2770,7 +2788,7 @@ def mpqs(n, retry = 1, max_retries = 3):
27702788 while True :
27712789 r = num
27722790 try :
2773- if len (str (r )) > 25 :
2791+ if len (str (r )) >= min_ :
27742792 d = mpqsfind (num )
27752793 ans .append (d )
27762794 r = num // d
@@ -2788,16 +2806,13 @@ def mpqs(n, retry = 1, max_retries = 3):
27882806 except TypeError :
27892807 ans = [x for x in _factor (num )[1 ]]
27902808 break
2791-
2792- if reduce (mul , ans ) == n :
2809+
2810+ checked = _check_factors (ans , n , retry )
2811+ if checked == 0 :
27932812 ans .sort ()
27942813 return ans
27952814
2796- print (f'Factor Error. The multiplication of { ans } is not { n } . Retry { retry } .' )
2797- if retry == max_retries :
2798- raise FactorError (f'Factor Error. The multiplication of { ans } is not { n } .' )
2799-
2800- return mpqs (n , retry + 1 )
2815+ return mpqs (n , checked )
28012816
28022817 return mpqs (n )
28032818
@@ -2841,6 +2856,7 @@ def double_point(P, curve):
28412856 def add_points (P1 , P2 , curve ):
28422857 if P1 .z == 0 :
28432858 return P2
2859+
28442860 if P2 .z == 0 :
28452861 return P1
28462862
@@ -2893,7 +2909,7 @@ def multiply_point(P, k, curve):
28932909
28942910 return P2
28952911
2896- def factor (n , mode = 1 , tries = 10 ):
2912+ def lenstra (n , mode = 1 , tries = 10 ):
28972913 factors = []
28982914 for i in (2 , 3 ):
28992915 while n % i == 0 :
@@ -2974,9 +2990,9 @@ def factor(n, mode = 1, tries = 10):
29742990 factors .sort ()
29752991 return factors
29762992
2977- return factor (n )
2993+ return lenstra (n )
29782994
2979- def factor_pollardpm1 (n ):
2995+ def factor_pollardpm1 (n , retry = 1 ):
29802996 '''
29812997 Return a list that has all factors of n.
29822998 '''
@@ -3011,10 +3027,14 @@ def factor(n):
30113027 else :
30123028 num = r
30133029
3014- ans .sort ()
3015- return ans
3030+ checked = _check_factors (ans , n , retry )
3031+ if checked == 0 :
3032+ ans .sort ()
3033+ return ans
3034+
3035+ return factor_pollardpm1 (n , checked )
30163036
3017- def factor_williamspp1 (n ):
3037+ def factor_williamspp1 (n , retry = 1 ):
30183038 '''
30193039 Return a list that has all factors of n.
30203040 '''
@@ -3068,8 +3088,12 @@ def factor(n, B = 10 ** 6):
30683088 else :
30693089 num = r
30703090
3071- ans .sort ()
3072- return ans
3091+ checked = _check_factors (ans , n , retry )
3092+ if checked == 0 :
3093+ ans .sort ()
3094+ return ans
3095+
3096+ return factor_williamspp1 (n , checked )
30733097
30743098def get_bits (n ):
30753099 return newkeys (n )[0 ].n
@@ -3107,7 +3131,8 @@ def test():
31073131 print (f'Leyland Primes of the second kind: { find_leylands_second_kind (58050 )} \n ' )
31083132 print (f'Woodall Primes: { find_woodalls (400 )} \n ' )
31093133 end_tm = time ()
3110- print (f'Prime Test Time: { round (end_tm - start_tm , 12 )} seconds.\n ' )
3134+ s = '\n ' if FACTOR_TEST else ''
3135+ print (f'Prime Test Time: { round (end_tm - start_tm , 12 )} seconds.' + s )
31113136
31123137 if FACTOR_TEST :
31133138 start_all = time ()
@@ -3183,7 +3208,7 @@ def test():
31833208 key_length = 92
31843209 key_large = get_bits (key_length )
31853210
3186- print ('Factor of A Very Large Number Test : (MPQS Method)\n ' )
3211+ print (f 'Factor of an RSA key of { key_length } bits : (MPQS Method)\n ' )
31873212 start_tm = time ()
31883213 print (f'Factor of { key_large } : { factor_mpqs (key_large )} ' )
31893214 end_tm = time ()
@@ -3192,46 +3217,11 @@ def test():
31923217 end_all = time ()
31933218 print (f'Factor Test Time: { round (end_all - start_all , 12 )} seconds.' )
31943219
3195- def add_args ():
3196- '''
3197- Add args.
3198- '''
3199- global args
3200- parser = ArgumentParser (description = 'A module to find all kinds of primes.' )
3201- parser .add_argument ('-n' , metavar = 'num' , type = int , help = 'The number' )
3202- parser .add_argument ('-method' , metavar = 'method' , type = str , help = 'The method of the factor function. (siqs, mpqs, lenstra, pollardpm1, williamspp1)' )
3203- parser .add_argument ('--is_prime' , metavar = 'is_prime' , const = is_prime , nargs = '?' , help = is_prime .__doc__ )
3204- parser .add_argument ('--all_primes' , metavar = 'all_primes' , const = all_primes , nargs = '?' , help = all_primes .__doc__ )
3205- parser .add_argument ('--factor' , metavar = 'factor' , const = factor_mpqs , nargs = '?' , help = factor_mpqs .__doc__ )
3206- args = parser .parse_args ()
3207- if args .is_prime :
3208- print (is_prime (args .n ))
3209-
3210- if args .all_primes :
3211- print (all_primes (args .n ))
3212-
3213- if args .factor :
3214- if args .method == 'siqs' :
3215- print (factor_siqs (args .n ))
3216-
3217- elif args .method == 'mpqs' :
3218- print (factor_mpqs (args .n ))
3219-
3220- elif args .method == 'lenstra' :
3221- print (factor_lenstra (args .n ))
3222-
3223- elif args .method == 'pollardpm1' :
3224- print (factor_pollardpm1 (args .n ))
3225-
3226- elif args .method == 'williamspp1' :
3227- print (factor_williamspp1 (args .n ))
3228-
3229- add_args ()
3230-
32313220if __name__ == '__main__' :
32323221 if version_info [0 ] == 3 and version_info [1 ] >= 6 :
32333222 if list (reversed (list (vars (args ).values ()))) == list (vars (args ).values ()):
32343223 test ()
3224+ print (factor_williamspp1 (137817 ))
32353225
32363226 else :
32373227 print ('The test method can\' t run in your python version.' )
0 commit comments