-
Notifications
You must be signed in to change notification settings - Fork 1
/
modexp_binary.py
84 lines (63 loc) · 2.68 KB
/
modexp_binary.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#FUNCTIONS FOR BITWISE MONTGOMERY MODULAR EXPONENTIATION
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def bit_val(a, n):
if (a & (1<<n)):
return 1
else:
return 0
#multiplication the Montgomery way
#---------------------------------
def montgomery_product(x, y, modulus, bitlength):
product = 0
for i in range(0, bitlength):
if bit_val(x, i):
product = product + y
if bit_val(product, 0):
product = product + modulus
product = product >> 1
if product >= modulus:
product = product - modulus
return product
#modular exponentiation in Montgomery form
#-----------------------------------------
def modular_exponentiation(one, base, exponent, modulus, bitlength):
exponential = one
for i in range(bitlength-1, -1, -1):
exponential = montgomery_product(exponential, exponential, modulus, bitlength)
if bit_val(exponent, i):
exponential = montgomery_product(base, exponential, modulus, bitlength)
return exponential
#modular exponentiation input - pick random numbers!
#---------------------------------------------------
base = 54 #610178765
exponent = 19 #865194045
modulus = 97 #16859994528005452387
#modulus = 11745174699710101459
print("expected:\n",base ** exponent % modulus) #uncomment for smaller numbers only
#CONVERT INPUT TO MONTGOMERY DOMAIN -- do not convert the exponent!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bitlength = 8 #4096
domain = 2**bitlength
#conversion with plain mathematics
#---------------------------------
#one = 1 * domain % modulus
#base = base * domain % modulus
#conversion of big numbers into Montgomery domain by Montgomery product
#----------------------------------------------------------------------
domain_square = domain ** 2 % modulus
one = montgomery_product(1, domain_square, modulus, bitlength)
base = montgomery_product(base, domain_square, modulus, bitlength)
#calculate modular exponential
#-----------------------------
result = modular_exponentiation(one, base, exponent, modulus, bitlength)
#REVERSE MONTGOMERY CONVERSION
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#with plain mathematics:
#-----------------------
#eulers_totient = modulus - 1 #because (modulus) is prime
#domain_to_minus_one = domain ** (eulers_totient - 1) % modulus
#result = result * domain_to_minus_one % modulus
#reverse convert big numbers with Montgomery product
#---------------------------------------------------
result = montgomery_product(result, 1, modulus, bitlength)
print("modular exponentiation with montgomery multiplication:\n", result)