Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Used gmpy2 functions instead of the standard ones or the while-loops implemented in Python #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 22 additions & 33 deletions CryptoAttacks/Math.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,7 @@ def gcd(*args):

if len(args) == 2:
a, b = args
while b:
a, b = b, a % b
return a
return gmpy2.gcd(a, b)
else:
d = 0
for number in args:
Expand All @@ -162,7 +160,7 @@ def lcm(*args):

if len(args) == 2:
a, b = args
return (a*b) // gcd(a, b)
return gmpy2.lcm(a, b)
else:
l = 1
for number in args:
Expand All @@ -184,12 +182,7 @@ def egcd(*args):

if len(args) == 2:
a, b = args
s0, t0, s1, t1 = 1, 0, 0, 1
while b:
q, a, b = a//b, b, a%b
s0, s1 = s1, s0 - q*s1
t0, t1 = t1, t0 - q*t1
return a, s0, t0
return gmpy2.gcdext(a, b)
else:
d, s, t = egcd(args[0], args[1])
coefficients = [s, t]
Expand All @@ -204,15 +197,11 @@ def egcd(*args):

def invmod(a, n):
"""Modular inverse. a*invmod(a) == 1 (mod n)"""
d, s, t = egcd(a, n)
if d != 1:
raise ValueError("Modular inverse doesn't exists ({}**(-1) % {})".format(a, n))
return s % n

return gmpy2.invert(a, n)

def legendre(a, p):
"""Legendre symbol"""
tmp = pow(a, (p-1)//2, p)
tmp = gmpy2.powmod(a, (p-1)//2, p)
return -1 if tmp == p-1 else tmp


Expand All @@ -228,26 +217,26 @@ def tonelli_shanks(n, p):
q >>= 1

if s == 1:
return pow(n, (p+1)//4, p)
return gmpy2.powmod(n, (p+1)//4, p)

z = 1
while legendre(z, p) != -1:
z += 1
c = pow(z, q, p)
c = gmpy2.powmod(z, q, p)

r = pow(n, (q+1)//2, p)
t = pow(n, q, p)
r = gmpy2.powmod(n, (q+1)//2, p)
t = gmpy2.powmod(n, q, p)
m = s
while t != 1:
i = 1
while i < m:
if pow(t, 2**i, p) == 1:
if gmpy2.powmod(t, 2**i, p) == 1:
break
i += 1
b = pow(c, 2**(m-i-1), p)
b = gmpy2.powmod(c, 2**(m-i-1), p)
r = (r*b) % p
t = (t * (b**2)) % p
c = pow(b, 2, p)
c = gmpy2.powmod(b, 2, p)
m = i
return r

Expand All @@ -269,8 +258,8 @@ def find_generator(p, factors):
a = randint(3, p-1)
if gcd(a, p-1) != 1:
continue
b = pow(a, (p-1)//one_factor, p)
y = pow(a, (p-1)//(one_factor**factors[one_factor]), p)
b = gmpy2.powmod(a, (p-1)//one_factor, p)
y = gmpy2.powmod(a, (p-1)//(one_factor**factors[one_factor]), p)
g *= y
return g

Expand Down Expand Up @@ -324,7 +313,7 @@ def generate_smooth_prime(bit_size, primitive_roots=[], smooth_bit_size=50, excl
if len(primitive_roots) > 0:
for factor, factor_power in factors.items():
for primitive_root in primitive_roots:
if pow(primitive_root, (n-1)//(factor**factor_power), n) == 1:
if gmpy2.powmod(primitive_root, (n-1)//(factor**factor_power), n) == 1:
are_primitive_roots = False
break

Expand All @@ -344,7 +333,7 @@ def babystep_giantstep(g, h, p, upper_bound):
g_j[g_j_tmp] = j
g_j_tmp = (g_j_tmp*g) % p

g_m = invmod(pow(g, m, p), p)
g_m = invmod(gmpy2.powmod(g, m, p), p)
y = h
for i in range(m):
if y in g_j:
Expand All @@ -370,18 +359,18 @@ def pohlig_hellman(g, h, n, n_order_factors):
log.debug('Pohlig-Hellman iteration {}/{}'.format(ci, loop_size))
ci += 1

gi = pow(g, no//(pi**ei), n) # gi have order pi**ei
hi = pow(h, no//(pi**ei), n) # hi is in <gi>
gi = gmpy2.powmod(g, no//(pi**ei), n) # gi have order pi**ei
hi = gmpy2.powmod(h, no//(pi**ei), n) # hi is in <gi>

xk = 0
gamma = pow(gi, pi**(ei-1), n) # gamma has order pi
gamma = gmpy2.powmod(gi, pi**(ei-1), n) # gamma has order pi
for k in range(ei):
hk = invmod(pow(gi, xk, n), n)
hk = pow(hk * hi, pi**(ei-1-k), n) # hk is in <gamma>
hk = invmod(gmpy2.powmod(gi, xk, n), n)
hk = gmpy2.powmod(hk * hi, pi**(ei-1-k), n) # hk is in <gamma>
dk = babystep_giantstep(gamma, hk, n, pi)
if dk is None:
return None
xk = (xk + pow(pi, k, pi**ei)*dk) % (pi**ei)
xk = (xk + gmpy2.powmod(pi, k, pi**ei)*dk) % (pi**ei)
xi.append(xk)

return crt(xi, [pi**ei for pi, ei in n_order_factors.items()])
30 changes: 15 additions & 15 deletions CryptoAttacks/PublicKey/rsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@ def factors_from_d(n, e, d):
g = random.randint(2, n - 2)
b = k // (2 ** power_of_two(k))
while b < k:
gb = pow(g, b, n)
if gb != 1 and gb != n - 1 and pow(gb, 2, n) == 1:
gb = gmpy2.powmod(g, b, n)
if gb != 1 and gb != n - 1 and gmpy2.powmod(gb, 2, n) == 1:
if gcd(gb - 1, n) != 1:
p = gcd(gb - 1, n)
else:
Expand Down Expand Up @@ -302,7 +302,7 @@ def small_e_msg(key, ciphertexts=None, max_times=100):
times = 0
for k in range(max_times):
msg, is_correct = gmpy2.iroot(ciphertext + times, key.e)
if is_correct and pow(msg, key.e, key.n) == ciphertext:
if is_correct and gmpy2.powmod(msg, key.e, key.n) == ciphertext:
msg = int(msg)
log.success("Found msg: {}, times=={}".format(i2h(msg), times // key.n))
recovered.append(msg)
Expand Down Expand Up @@ -461,7 +461,7 @@ def faulty(key, padding=None):
message = pair['plain']
if padding:
message = padding(message)
p = gmpy2.gcd(pow(signature, key.e) - message, key.n)
p = gmpy2.gcd(gmpy2.pow(signature, key.e) - message, key.n)
if p != 1 and p != key.n:
log.info("Found p={}".format(p))
new_key = RSAKey.construct(key.n, key.e, p=p, identifier=key.identifier + '-private')
Expand Down Expand Up @@ -666,10 +666,10 @@ def bleichenbacher_signature_forgery(key, garbage='suffix', hash_function='sha1'
for round_error in range(-5, 5):
signature, _ = gmpy2.iroot(plaintext, key.e)
signature = int(signature + round_error)
test_prefix = i2b(pow(signature, key.e, key.n), size=key.size)[:len(plaintext_prefix)]
test_prefix = i2b(gmpy2.powmod(signature, key.e, key.n), size=key.size)[:len(plaintext_prefix)]
if test_prefix == plaintext_prefix:
log.info("Got signature: {}".format(signature))
log.debug("signature**e % n == {}".format(i2h(pow(signature, key.e, key.n), size=key.size)))
log.debug("signature**e % n == {}".format(i2h(gmpy2.powmod(signature, key.e, key.n), size=key.size)))
key.texts[text_no]['cipher'] = signature
signatures[text_no] = signature
break
Expand Down Expand Up @@ -702,7 +702,7 @@ def bleichenbacher_signature_forgery(key, garbage='suffix', hash_function='sha1'
signature_prefix = i2b(int(signature_prefix), size=key.size)[:-len(signature_suffix)]

signature = b2i(signature_prefix + signature_suffix)
test_plaintext = i2b(pow(signature, key.e, key.n), size=key.size)
test_plaintext = i2b(gmpy2.powmod(signature, key.e, key.n), size=key.size)
if bytes(b'\x00') not in test_plaintext[2:-len(plaintext_suffix)]:
if test_plaintext[:3] == plaintext_prefix[:3] and test_plaintext[
-len(plaintext_suffix):] == plaintext_suffix:
Expand Down Expand Up @@ -859,7 +859,7 @@ def update_intervals(M, B, s, n):
def find_si(si_start, si_max=None):
si_new = si_start
while si_max is None or si_new < si_max:
cipheri = (cipher_blinded * pow(si_new, e, n)) % n
cipheri = (cipher_blinded * gmpy2.powmod(si_new, e, n)) % n
if pkcs15_padding_oracle(cipheri, **kwargs):
return si_new
si_new += 1
Expand All @@ -871,7 +871,7 @@ def find_si(si_start, si_max=None):

n = key.n
e = key.e
B = pow(2, key.size - 16)
B = gmpy2.pow(2, key.size - 16)

# step 1
log.debug('Blinding the ciphertext (to make it PKCS1.5 confirming)')
Expand All @@ -884,7 +884,7 @@ def find_si(si_start, si_max=None):
si += 1
else:
si = random.randint(2, 1 << (key.size - 16))
cipher_blinded = (cipher * pow(si, e, n)) % n
cipher_blinded = (cipher * gmpy2.powmod(si, e, n)) % n
Mi = [(2 * B, 3 * B - 1)]
s0 = si
log.debug('Found s{}: {}'.format(i, hex(si)))
Expand Down Expand Up @@ -984,10 +984,10 @@ def floor(a, b):
# step 1
log.debug('step 1')
f1 = 2
cipheri = (cipher * pow(f1, e, n)) % n
cipheri = (cipher * gmpy2.powmod(f1, e, n)) % n
while oaep_padding_oracle(cipheri, **kwargs):
f1 *= 2
cipheri = (cipher * pow(f1, e, n)) % n
cipheri = (cipher * gmpy2.powmod(f1, e, n)) % n

log.debug('step 1 done')
log.debug('Found f1: {}'.format(hex(f1)))
Expand All @@ -996,10 +996,10 @@ def floor(a, b):
log.debug('step 2')
f1_half = f1 // 2
f2 = int(floor(n + B, B)) * f1_half
cipheri = (cipher * pow(f2, e, n)) % n
cipheri = (cipher * gmpy2.powmod(f2, e, n)) % n
while not oaep_padding_oracle(cipheri, **kwargs):
f2 += f1_half
cipheri = (cipher * pow(f2, e, n)) % n
cipheri = (cipher * gmpy2.powmod(f2, e, n)) % n

log.debug('step 2 done')
log.debug('Found f2: {}'.format(hex(f2)))
Expand All @@ -1013,7 +1013,7 @@ def floor(a, b):
i = floor(f_tmp * m_min, n)
f3 = ceil(i * n, m_min)

cipheri = (cipher * pow(f3, e, n)) % n
cipheri = (cipher * gmpy2.powmod(f3, e, n)) % n
if oaep_padding_oracle(cipheri, **kwargs):
m_max = floor(i * n + B, f3)
else:
Expand Down