9
9
from functools import reduce
10
10
from operator import mul
11
11
from sys import version_info
12
- from rsa import newkeys
13
12
from argparse import ArgumentParser
14
13
15
14
NUMPY_ENABLED = True
20
19
except ImportError :
21
20
NUMPY_ENABLED = False
22
21
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 ()))
24
27
25
- PRIME_TEST = True
26
- FACTOR_TEST = True
28
+ except ImportError :
29
+ FACTOR_TEST = False
27
30
28
31
LEFT = 'left'
29
32
RIGHT = 'right'
@@ -44,6 +47,21 @@ def _check_num(n):
44
47
if n <= 0 :
45
48
raise ValueError ('The number of argument n should be greater than 0, got {n}' .format (** locals ()))
46
49
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
+
47
65
def is_prime (n ):
48
66
'''
49
67
If n is prime, return True.
@@ -2753,14 +2771,14 @@ def mpqsfind(n, s = 0, f = 0, m = 0):
2753
2771
2754
2772
X = floorsqrt (X ) % M .number
2755
2773
if X != Y :
2756
- differences .append (X - Y )
2774
+ differences .append (X - Y )
2757
2775
2758
2776
for diff in differences :
2759
2777
divisor = gcd (diff , N )
2760
2778
if 1 < divisor < N :
2761
2779
return divisor
2762
2780
2763
- def mpqs (n , retry = 1 , max_retries = 3 ):
2781
+ def mpqs (n , retry = 1 , min_ = 20 ):
2764
2782
num = n
2765
2783
ans = []
2766
2784
if is_prime (n ):
@@ -2770,7 +2788,7 @@ def mpqs(n, retry = 1, max_retries = 3):
2770
2788
while True :
2771
2789
r = num
2772
2790
try :
2773
- if len (str (r )) > 25 :
2791
+ if len (str (r )) >= min_ :
2774
2792
d = mpqsfind (num )
2775
2793
ans .append (d )
2776
2794
r = num // d
@@ -2788,16 +2806,13 @@ def mpqs(n, retry = 1, max_retries = 3):
2788
2806
except TypeError :
2789
2807
ans = [x for x in _factor (num )[1 ]]
2790
2808
break
2791
-
2792
- if reduce (mul , ans ) == n :
2809
+
2810
+ checked = _check_factors (ans , n , retry )
2811
+ if checked == 0 :
2793
2812
ans .sort ()
2794
2813
return ans
2795
2814
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 )
2801
2816
2802
2817
return mpqs (n )
2803
2818
@@ -2841,6 +2856,7 @@ def double_point(P, curve):
2841
2856
def add_points (P1 , P2 , curve ):
2842
2857
if P1 .z == 0 :
2843
2858
return P2
2859
+
2844
2860
if P2 .z == 0 :
2845
2861
return P1
2846
2862
@@ -2893,7 +2909,7 @@ def multiply_point(P, k, curve):
2893
2909
2894
2910
return P2
2895
2911
2896
- def factor (n , mode = 1 , tries = 10 ):
2912
+ def lenstra (n , mode = 1 , tries = 10 ):
2897
2913
factors = []
2898
2914
for i in (2 , 3 ):
2899
2915
while n % i == 0 :
@@ -2974,9 +2990,9 @@ def factor(n, mode = 1, tries = 10):
2974
2990
factors .sort ()
2975
2991
return factors
2976
2992
2977
- return factor (n )
2993
+ return lenstra (n )
2978
2994
2979
- def factor_pollardpm1 (n ):
2995
+ def factor_pollardpm1 (n , retry = 1 ):
2980
2996
'''
2981
2997
Return a list that has all factors of n.
2982
2998
'''
@@ -3011,10 +3027,14 @@ def factor(n):
3011
3027
else :
3012
3028
num = r
3013
3029
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 )
3016
3036
3017
- def factor_williamspp1 (n ):
3037
+ def factor_williamspp1 (n , retry = 1 ):
3018
3038
'''
3019
3039
Return a list that has all factors of n.
3020
3040
'''
@@ -3068,8 +3088,12 @@ def factor(n, B = 10 ** 6):
3068
3088
else :
3069
3089
num = r
3070
3090
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 )
3073
3097
3074
3098
def get_bits (n ):
3075
3099
return newkeys (n )[0 ].n
@@ -3107,7 +3131,8 @@ def test():
3107
3131
print (f'Leyland Primes of the second kind: { find_leylands_second_kind (58050 )} \n ' )
3108
3132
print (f'Woodall Primes: { find_woodalls (400 )} \n ' )
3109
3133
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 )
3111
3136
3112
3137
if FACTOR_TEST :
3113
3138
start_all = time ()
@@ -3183,7 +3208,7 @@ def test():
3183
3208
key_length = 92
3184
3209
key_large = get_bits (key_length )
3185
3210
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 ' )
3187
3212
start_tm = time ()
3188
3213
print (f'Factor of { key_large } : { factor_mpqs (key_large )} ' )
3189
3214
end_tm = time ()
@@ -3192,46 +3217,11 @@ def test():
3192
3217
end_all = time ()
3193
3218
print (f'Factor Test Time: { round (end_all - start_all , 12 )} seconds.' )
3194
3219
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
-
3231
3220
if __name__ == '__main__' :
3232
3221
if version_info [0 ] == 3 and version_info [1 ] >= 6 :
3233
3222
if list (reversed (list (vars (args ).values ()))) == list (vars (args ).values ()):
3234
3223
test ()
3224
+ print (factor_williamspp1 (137817 ))
3235
3225
3236
3226
else :
3237
3227
print ('The test method can\' t run in your python version.' )
0 commit comments