Brute force attack for discrete log problem (Python) - python

I'm still learning Python and trying to wrap my mind around brute force attacks using for loops in Python. I made this for loop to try every number from 0 to 999999 and store it in the variable n. Instead of letting my for look run forever, I want it to stop at a specific scalarmult(n,P) value. For example, let's say I want the for loop to end when print(scalarmult(n,P)) prints, (111111,2334897).
p = 1000003
class Fp:
def __init__(self,x):
self.int = x % p
def __str__(self):
return str(self.int)
__repr__ = __str__
Fp.__eq__ = \
lambda a,b: a.int == b.int
Fp.__add__ = \
lambda a,b: Fp(a.int + b.int)
Fp.__sub__ = \
lambda a,b: Fp(a.int - b.int)
Fp.__mul__ = \
lambda a,b: Fp(a.int * b.int)
def clockadd(P1, P2):
x1,y1 = P1
x2,y2 = P2
x3 = x1*y2+y1*x2
y3 = y1*y2-x1*x2
return x3,y3
P = (Fp(1000),Fp(2))
def scalarmult(n,P):
if n == 0: return (Fp(0), Fp(1))
if n == 1: return P
Q = scalarmult(n//2,P)
Q = clockadd(Q,Q)
if n % 2: Q=clockadd(P,Q)
return Q
#(947472, 736284)
for n in range(0,10):
i = scalarmult(n,P)
print(n, i) #i.e. 6 (780000, 1351)
if n == 780000 and P == 1351: #should stop the for loop at iteration 7 which is 6 (780000, 1351)
break

Add an if statement inside the loop, after the print
if n == 111111 and p == 2334897:
break

Related

Python Hw, bisection Method

Part A - Bisection Method
Write a function called bisection(n, p) that asks the user to enter a mathematical function f(x)
and two boundary points in order to solve for r such that f(r) = 0 using bisection method.
The function terminates when the solution r is found or when the maximum number of iterations
n is reached (default n = 100), whichever occurs first.
def bisection(n = 100, p = 0.0001):
# code goes below
fx = input("f(x) = ")
a = float(input("Boundary A: "))
x = a
fa = eval(fx)
b = float(input("Boundary B: "))
x = b
fb = eval(fx)
i = 0
if (fa * fb >= 0):
print("Bisection method fails")
return
while(i < n):
m = a + b / 2
x = m
fm = eval(fx)
if(fm * fa < 0):
a = a
b = m
if (fm * fb < 0):
a = m
b = b
i = i + 1
if (fm == 0):
return m
pass
When I input: f(x) = x - 1
Boundary A: 0
Boundary B: 3
No answer is printed so I'm very confused?!
There are lots of problems with this code. For some reason you defined p and never passed it again, I assume it stands for epsilon. You defined midpoint as
a+b/2
which is equivalent to
a+(b/2)
but you need
(a+b)/2
.
Statement
if (fm == 0):
this statement would probably never run because it is hard to get that close to a root for a few iterations.
Instead, use
if (abs(fm<p)):
Modified code
def bisection(n = 250, p = 10**-6):
# code goes below
fx = input("f(x) = ")
a = float(input("Boundary A: "))
x = a
fa = eval(fx)
b = float(input("Boundary B: "))
x = b
fb = eval(fx)
for i in range(1, n+1):
m = (a + b)/2
x = m
fm = eval(fx)
if(fm * fa < 0):
a = a
b = m
elif (fm * fa > 0):
a = m
b = b
elif (abs(fm<p)):
return m
print(bisection())
Output:
f(x) = x - 1
Boundary A: 0
Boundary B: 3
1.0

Python calls the same function in a loop, and uses the return value of the last call as the parameter of this call

This is kmeans I wrote. I want to call this function cyclically to repeatedly calculate the distance to the center point and enter the return as parameter
the first input is (b[0,:],b[1,:])
def DIV(point1,point2):
plt.figure()
c = []
d = []
for i in range(1000):
dist1 = np.linalg.norm(Z[i] - point1)
dist2 = np.linalg.norm(Z[i] - point2)
if dist1 > dist2:
c.append(Z[i])
else:
d.append(Z[i])
C = np.array(c)
D = np.array(d)
plt.scatter(C[:,0],C[:,1],s=16.,color='green')
plt.scatter(D[:,0],D[:,1],s=16.,color='yellow')
center1 = C.mean(axis=0)
center2 = D.mean(axis=0)
plt.scatter(center1[0],center1[1],marker ='x',s=16.,color='red')
plt.scatter(center2[0],center2[1],marker ='x',s=16.,color='red')
return center1,center2
Your function and background don't matter much, sounds like you are basically trying to do a "fixed point" function based on your response to my comment:
def fix(func, initial, max_iter):
prev = func(initial)
iteration = 1
while True:
curr = func(prev)
if curr == prev or iteration > max_iter:
break
prev = curr
iteration += 1
return curr
For your specific case, you could then write
div = lambda (a, b): DIV(a, b)
result = fix(div, (b[0,:],b[1,:]), max_iter=1000)
if you wanted to use the same logic inline, instead of using more generic logic, you could write
prev = DIV(b[0,:],b[1,:])
iteration = 1
while True:
curr = DIV(*prev)
if curr == prev or iteration > 1000:
break
prev = curr
iteration += 1
result = curr
I used very cumbersome loops and functions to control its iteration
def paste(head, start=0, stop=0, step=1, sep=''):
return [f'{head}{sep}{i}' for i in range(start, stop, step)]
def loop(n):
k = paste('a', 0, n)
k[0],k[1] = DIV(b[0,:],b[1,:])
for i in range(0,n,2):
k[i],k[i+1] = DIV(k[i],k[i+1])
for j in range(2,n,2):
k[j],k[j+1] = DIV(k[i],k[i+1])
loop(6)

Why does the encryption/decryption in my RSA code not work?

I'm currently coding a simplified RSA algorithm for a project at school but can't get it to work.
I've based the code off of the formulae c = m^e(mod N) and (c^d)mod N. The encryption function works to produce what looks like a feasible output but when I put it into the decryption function it either doesn't return the message correctly or gives me this error:
ValueError: chr() arg not in range(0x110000)
My code:
import random
import math
def is_prime(x):
for i in range(2,int(math.sqrt(x))+1):
if x % i == 0:
return False
break
return True
def gcd(a, b):
if (b == 0):
return a
else:
return gcd(b, a % b)
def generate_p_and_q(p,q):
p_and_q = []
p_and_q.append(p)
p_and_q.append(q)
return p_and_q
def generate_phi(p,q):
p_and_q = generate_p_and_q(p,q)
phi = (p_and_q[0] - 1)*(p_and_q[1] - 1)
return phi
def generate_N(p,q):
p_and_q = generate_p_and_q(p,q)
N = (p_and_q[0])*(p_and_q[1])
return N
def generate_e(p,q):
phi = generate_phi(p,q)
with open('First500Primes.txt') as f:
lines = f.read().splitlines()
for i in lines:
if int(i) > 1 and int(i)< phi:
if gcd(int(i), phi) == 1:
e = int(i)
break
return e
def encrypt_RSA():
encrypted = []
message = input("Enter a message to encrypt:")
message.lower()
with open('First500Primes.txt') as f:
lines = f.read().splitlines()
valid = False
choice = input("Do you want to: \nA: enter a key \nB: use a random key?\n")
if choice.lower() == 'a':
p = int(input("Enter a key - this must be a prime number between 0 and 500:"))
q = int(input("Enter a key - this must be a prime number between 0 and 500:\n"))
while valid != True:
valid = is_prime(p) and is_prime(q)
if valid == False:
print("Your numbers were not prime!")
p = int(input("Enter a key - this must be a prime number between 0 and 500:"))
q = int(input("Enter a key - this must be a prime number between 0 and 500:\n"))
else:
x = random.randint(0, 499)
y = random.randint(0, 499)
p = int(lines[x])
q = int(lines[y])
generate_p_and_q(p,q)
e = generate_e(p,q)
N = generate_N(p,q)
for char in message:
encrypted.append((ord(char) ** e) % N)
result = ''
for i in encrypted:
result = result + str(i)
print("encrypted message: " + result)
info = [encrypted, N, e]
return (info)
encrypt_RSA()
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def calculate_d(a,m):
g,x,y = egcd(a,m)
if g != 1:
return None
else:
return x%m
def calculate_phi(N):
with open('First500Primes.txt') as f:
lines = f.read().splitlines()
for num in lines:
if N%int(num) == 0:
p = int(num)
q = N/int(num)
phi = (p-1)*(q-1)
return int(phi)
def decrypt_RSA():
encrypted = encrypt_RSA()
encrypted_message, N, e = encrypted[0], encrypted[1], encrypted[2]
print(N)
phi = calculate_phi(N)
d = calculate_d(phi,e)
print("D: " + str(d))
message = []
encrypted_message = (encrypted[0])
for c in encrypted_message:
m = (c**d) % N
print(m)
message.append(chr(m))
print(message)
decrypt_RSA()
I need the code to firstly encrypt the message with the encrypt function then decrypt it with the decrypt function, so the encrypted and original message should be displayed.
Could someone tell me whats wrong with my code (since I'm still in school, it may need to be simplified), any additional feedback would be greatly appreciated.
After a bit of debugging, the problem is that the function calculate_d() does not seem to calculate the right number. It is solved when we invert the params of one of your function. Change this line
d = calculate_d(phi, e)
to this:
d = calculate_d(e, phi)
That got it working for me.
Also, since you asked for suggestions to improve your code, I made a few (a lot) improvements. Some ideas:
I replaced the parts that read the prime number file with a prime number generator, but that is just because I didn't have the file at hand. Choose whichever you like best.
Invoke the main functions inside a if __name__ == '__main__':. Read about it here.
I moved the input prompts outside of the encryption code. Implement those parts as needed (random or prompting user for input) and just pass the result to the function for encryption.
My version:
def generate_primes():
"""
Generate an infinite sequence of prime numbers.
Sieve of Eratosthenes
Code by David Eppstein, UC Irvine, 28 Feb 2002
http://code.activestate.com/recipes/117119/
https://stackoverflow.com/a/568618/9225671
"""
# Maps composites to primes witnessing their compositeness.
# This is memory efficient, as the sieve is not "run forward"
# indefinitely, but only as long as required by the current
# number being tested.
D = {}
# The running integer that's checked for primeness
q = 2
while True:
if q not in D:
# q is a new prime.
# Yield it and mark its first multiple that isn't
# already marked in previous iterations
yield q
D[q * q] = [q]
else:
# q is composite. D[q] is the list of primes that
# divide it. Since we've reached q, we no longer
# need it in the map, but we'll mark the next
# multiples of its witnesses to prepare for larger
# numbers
for p in D[q]:
D.setdefault(p + q, []).append(p)
del D[q]
q += 1
def choose_p_and_q():
p_i = random.randint(0, 100)
q_i = random.randint(0, 100)
p = 0
q = 0
for i, n in enumerate(generate_primes()):
if i <= p_i:
p = n
if i <= q_i:
q = n
if i > p_i and i > q_i:
break
return p, q
def generate_n(p, q):
return p * q
def generate_phi(p, q):
return (p - 1) * (q - 1)
def generate_e(phi):
e = None
for n in generate_primes():
if math.gcd(n, phi) == 1:
e = n
if n >= phi:
if e is None:
raise ValueError('no suitable prime number found; reached {}'.format(n))
# return the highest prime number found
return e
def find_p_and_q_from_n(n):
for i in generate_primes():
if n % i == 0:
p = i
q, remainder = divmod(n, p)
if remainder == 0:
return p, q
def egcd(a, b):
if a == 0:
return b, 0, 1
else:
g, y, x = egcd(b % a, a)
return g, x - (b // a) * y, y
def calculate_d(phi, e):
g, x, _ = egcd(phi, e)
if g == 1:
return x % e
raise ValueError('no modular multiplicative inverse found')
def encrypt_rsa(msg):
p, q = choose_p_and_q()
n = generate_n(p, q)
phi = generate_phi(p, q)
e = generate_e(phi)
print()
print('ENCRYPT')
print('p ', p)
print('q ', q)
print('n ', n)
print('phi ', phi)
print('e ', e)
encrypted_list = []
for char in msg:
m = (ord(char) ** e) % n
encrypted_list.append(m)
print('msg ', list(msg))
print('encrypted_list', encrypted_list)
return encrypted_list, n, e
def decrypt_rsa(encrypted_list, n, e):
p, q = find_p_and_q_from_n(n)
phi = generate_phi(p, q)
d = calculate_d(e, phi)
print()
print('DECRYPT')
print('p ', p)
print('q ', q)
print('n ', n)
print('phi ', phi)
print('e ', e)
print('d ', d)
decrypted_list = []
for elem in encrypted_list:
m = (elem**d) % n
decrypted_list.append(chr(m))
print('decrypted_list', decrypted_list)
if __name__ == '__main__':
msg = input('Enter a message to encrypt:').strip()
data = encrypt_rsa(msg)
decrypt_rsa(*data)

Proper way to benchmark python code

I have the following modulo exponentiation code and I would like to benchmark a few lines in the function.
One line is:
temp = square(temp)
But python complains that global name 'square' is not defined. Also how can I benchmark the line with
ret = temp % n
Do I also need to write it into a function?
import math
import timeit
def int2baseTwo(x):
"""x is a positive integer. Convert it to base two as a list of integers
in reverse order as a list."""
# repeating x >>= 1 and x & 1 will do the trick
assert x >= 0
bitInverse = []
while x != 0:
bitInverse.append(x & 1)
x >>= 1
return bitInverse
def square(a):
return a ** 2
def modExp(a, d, n):
"""returns a ** d (mod n)"""
assert d >= 0
assert n >= 0
base2D = int2baseTwo(d)
#print 'base2D = ', base2D
base2DLength = len(base2D)
#print 'base2DLength = ', base2DLength
modArray = []
result = 1
temp = 1
for i in range(0, base2DLength):
if i == 0:
temp = a
continue
print(timeit.timeit("temp = square(temp)", setup="from __main__ import modExp"))
if base2D[i] == 1:
temp = temp * a
ret = temp % n
return ret
if __name__=="__main__":
print(timeit.timeit("modExp(1000,100,59)", setup="from __main__ import modExp"))

(Z3Py) checking all solutions for equation

In Z3Py, how can I check if equation for given constraints have only one solution?
If more than one solution, how can I enumerate them?
You can do that by adding a new constraint that blocks the model returned by Z3.
For example, suppose that in the model returned by Z3 we have that x = 0 and y = 1. Then, we can block this model by adding the constraint Or(x != 0, y != 1).
The following script does the trick.
You can try it online at: http://rise4fun.com/Z3Py/4blB
Note that the following script has a couple of limitations. The input formula cannot include uninterpreted functions, arrays or uninterpreted sorts.
from z3 import *
# Return the first "M" models of formula list of formulas F
def get_models(F, M):
result = []
s = Solver()
s.add(F)
while len(result) < M and s.check() == sat:
m = s.model()
result.append(m)
# Create a new constraint the blocks the current model
block = []
for d in m:
# d is a declaration
if d.arity() > 0:
raise Z3Exception("uninterpreted functions are not supported")
# create a constant from declaration
c = d()
if is_array(c) or c.sort().kind() == Z3_UNINTERPRETED_SORT:
raise Z3Exception("arrays and uninterpreted sorts are not supported")
block.append(c != m[d])
s.add(Or(block))
return result
# Return True if F has exactly one model.
def exactly_one_model(F):
return len(get_models(F, 2)) == 1
x, y = Ints('x y')
s = Solver()
F = [x >= 0, x <= 1, y >= 0, y <= 2, y == 2*x]
print get_models(F, 10)
print exactly_one_model(F)
print exactly_one_model([x >= 0, x <= 1, y >= 0, y <= 2, 2*y == x])
# Demonstrate unsupported features
try:
a = Array('a', IntSort(), IntSort())
b = Array('b', IntSort(), IntSort())
print get_models(a==b, 10)
except Z3Exception as ex:
print "Error: ", ex
try:
f = Function('f', IntSort(), IntSort())
print get_models(f(x) == x, 10)
except Z3Exception as ex:
print "Error: ", ex
The python function below is a generator of models for formulas that contain both constants and functions.
import itertools
from z3 import *
def models(formula, max=10):
" a generator of up to max models "
solver = Solver()
solver.add(formula)
count = 0
while count<max or max==0:
count += 1
if solver.check() == sat:
model = solver.model()
yield model
# exclude this model
block = []
for z3_decl in model: # FuncDeclRef
arg_domains = []
for i in range(z3_decl.arity()):
domain, arg_domain = z3_decl.domain(i), []
for j in range(domain.num_constructors()):
arg_domain.append( domain.constructor(j) () )
arg_domains.append(arg_domain)
for args in itertools.product(*arg_domains):
block.append(z3_decl(*args) != model.eval(z3_decl(*args)))
solver.add(Or(block))
x, y = Ints('x y')
F = [x >= 0, x <= 1, y >= 0, y <= 2, y == 2*x]
for m in models(F):
print(m)
Referencing http://theory.stanford.edu/~nikolaj/programmingz3.html#sec-blocking-evaluations
def all_smt(s, initial_terms):
def block_term(s, m, t):
s.add(t != m.eval(t))
def fix_term(s, m, t):
s.add(t == m.eval(t))
def all_smt_rec(terms):
if sat == s.check():
m = s.model()
yield m
for i in range(len(terms)):
s.push()
block_term(s, m, terms[i])
for j in range(i):
fix_term(s, m, terms[j])
yield from all_smt_rec(terms[i:])
s.pop()
yield from all_smt_rec(list(initial_terms))
This indeed performs quite better from Leonardo's own answer (considering his answer is quite old)
start_time = time.time()
v = [BitVec(f'v{i}',3) for i in range(6)]
models = get_models([Sum(v)==0],8**5)
print(time.time()-start_time)
#211.6482105255127s
start_time = time.time()
s = Solver()
v = [BitVec(f'v{i}',3) for i in range(6)]
s.add(Sum(v)==0)
models = list(all_smt(s,v))
print(time.time()-start_time)
#13.375828742980957s
Splitting the search space into disjoint models creates a huge difference as far as I have observed
The answer given by Himanshu Sheoran cites the paper https://theory.stanford.edu/%7Enikolaj/programmingz3.html#sec-blocking-evaluations
Unfortunately there was a bug in the implementation given in the paper at that time which was quoted in that answer. The function has since been corrected.
For posterity, here's the correct version of the code:
def all_smt(s, initial_terms):
def block_term(s, m, t):
s.add(t != m.eval(t, model_completion=True))
def fix_term(s, m, t):
s.add(t == m.eval(t, model_completion=True))
def all_smt_rec(terms):
if sat == s.check():
m = s.model()
yield m
for i in range(len(terms)):
s.push()
block_term(s, m, terms[i])
for j in range(i):
fix_term(s, m, terms[j])
yield from all_smt_rec(terms[i:])
s.pop()
yield from all_smt_rec(list(initial_terms))

Categories

Resources