how can I handle large numbers in Python? - python

I would like to make a Python code for Paillier Encryption and I have made the code, which works well with small number e.g. 32bit. But I would like to make it work even though the number is very very large (till 1024 bit)
So I tried this code which p,q (random choosed Primenumber)
here is the code
from random import randint
import libnum
import sys
import random
import numpy as np ## in order to save the time
def gcd(a,b):
"""Compute the greatest common divisor of a and b"""
while b > 0:
a, b = b, a % b
return a
def lcm(a, b):
"""Compute the lowest common multiple of a and b"""
return a * b // gcd(a, b)
def L(x,n):
return ((x-1)//n)
#%% Key generation (Schlüsselerzeugung)
find_primenumber=2**513
# um die
a = [False,False] + [True]*(find_primenumber-1)
primes=[]
# Algorism of eratosthenes
for i in range(2,find_primenumber+1):
if a[i]:
primes.append(i)
for j in range(2*i, find_primenumber+1, i):
a[j] = False
# print('the choosable prime numbers are : ',primes)
p= random.sample(primes, 2)[0]
q=random.sample(primes, 2)[1] ## two prime numbers are randomly choosed
# öffentliche Schlüssel public key (n,g)
n = p*q
# um Schlüssellänge zu vergrößen, muss n noch größer werden
# sys.getsizeof(n)
# in case n = 2499995600000711 size of n is 32
g = n+1 #Pick a random integer g in the set Z∗n2 (integers between 1 and n2)
gLambda = lcm(p-1,q-1) ## in Matlab cipher = lambda
m= str(input('Enter plaintext :')) #must be string type
m= list(m)
m_list=[]
for i in range(0,len(m)):
m_list.append(ord(m[i])) ## must be saved as a list
m_1=np.array(m_list)
if (len(sys.argv)>1):
m=int(sys.argv[1])
if (len(sys.argv)>2):
p=int(sys.argv[2])
if (len(sys.argv)>3):
q=int(sys.argv[3])
if (p==q):
print("P and Q cannot be the same")
sys.exit()
l = (pow(g, gLambda, n*n)-1)//n
gMu = libnum.invmod(l, n)
if (gcd(g,n*n)==1):
print("g is relatively prime to n*n")
else:
print("WARNING: g is NOT relatively prime to n*n. Will not work!!!")
# geheime Schlüssel (private key)
r=[]
for i in range(0,len(m)):
r.append(randint(1,n))
#%% Encryption
# changed: pow(a,b,n) for modular exponentiation a^b mod n
# --> much faster than the standard pow()
# shortened the code
c=[]
for i in range(0,len(m)):
k1 = pow(g, m_list[i], n**2)
k2 = pow(r[i], n, n**2)
c.append((k1*k2)%(n**2));
but I get this answer from the Console
OverflowError: cannot fit 'int' into an index-sized integer
How can I fix it and make it work even the find_primenumber is large enough?

Related

Python - RSA decryption does not return original message (very simple, short program)

So I am trying to create a very simple RSA encryption/decryption program where I only encrypt/decrypt int numbers. All works fine except for one problem. Sometimes my decrypted number (message) does not match my original number (the message I needed to encrypt and decrypt). This seems to happen whenever my inputted number (message) is close to my the number in my 'n' variable (n=p*q where p and q are prime numbers). I have browsed Stackoverflow a bit now and have found out that RSA algoritms cannot properly decrypt messages that are greater than 'n'. But in my case it fails to decrypt messages that are close to 'n'. If n=35 and my input number (the number to encrypt/decrypt) is 32, the program does not properly decrypt it back to 32 despite 32 being lower than 35 (works for 31, 30 ... though). Why?
Code:
import math
def isPrime(n):
if n>=2:
for m in range(2, int(math.sqrt(n)+1)):
if n%m == 0:
return False
return True
else:
return False
def gcd(x, y):
while y != 0:
(x, y) = (y, x % y)
return x
def phi(n):
amount = 0
for k in range(1, n + 1):
if gcd(n, k) == 1:
amount += 1
return amount
def findPubE(n, phiN):
for e in range(3, n, 2):
if gcd(e,phiN)==1:
return e
else:
raise AssertionError("cannot find 'e'")
def multiplicative_inverse(a, b):
"""Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
"""
# r = gcd(a,b) i = multiplicitive inverse of a mod b
# or j = multiplicitive inverse of b mod a
# Neg return values for i or j are made positive mod b or a respectively
# Iterateive Version is faster and uses much less stack space
x = 0
y = 1
lx = 1
ly = 0
oa = a # Remember original a/b to remove
ob = b # negative values from return results
while b != 0:
q = a // b
(a, b) = (b, a % b)
(x, lx) = ((lx - (q * x)), x)
(y, ly) = ((ly - (q * y)), y)
if lx < 0:
lx += ob # If neg wrap modulo orignal b
if ly < 0:
ly += oa # If neg wrap modulo orignal a
# return a , lx, ly # Return only positive values
return lx
def encrypt(m,e,n):
return (m^(e)) % n
def decrypt(M, d):
return M^(d)
def main():
p=int(input("Input first prime number (p): "))
q=int(input("Input second prime number (q): "))
n=p*q
print("n = ",n)
msg= int(input("Input message: "))
assert msg < n
phiN=(p-1)*(q-1)
e = findPubE(n,phiN)
d = multiplicative_inverse(e,phiN)
encryptedMsg = encrypt(msg,e,n)
decryptedMsg = decrypt(encryptedMsg,d)
assert isPrime(p) and isPrime(q)
print("phi(n) = ",phiN)
print("e = ",e)
print("d = ",d)
print("Encrypted message: ",encryptedMsg)
print("Decrypted message: ",decryptedMsg)
main()
Solved it! I made two little mistakes in my code. First one was that I assumed that the "^" symbol meant "to the power of" in Python (the correct symbol is "**") and the second one was that I forgot to add "mod n" to the line in my decrypt() function (so return M**(d) % n instead of return M^(d)).

Proper Carmichael Function

I'm creating all the necessary functions for RSA algorithm. Unfortunately i can't seem to a make proper Carmichael function.
These are the functions that i've written:
def gcd(a, b): # Greatest Common Divisor Generator (Euclidean Algorithm)
while b != 0: # While remainder exists
t = b # Initially r[k-1]
b = a % t # Initially r[k] = r[k-2] mod r[k-1] (where r[k-2] is a)
a = t # Predecessor of remainder (b)
return a
def phi(n): # Leonard Euler's Totient Function
y = 0
for k in range(1, n + 1): # Phi(+n) is the number of integers k in the range (1 <= k >= n)...
if gcd(n, k) == 1: # for which gcd(n, k) = 1
y += 1
return y
def carmichael(n): # Robert Daniel Carmichael's Function
y = (phi(n) * 1/2) if (n > 4 and ((n & (n - 1)) == 0)) else phi(n) # phi(n) * 1/2 if 2^x = n, else phi(n) * 1
return y
I'm using totient function for number generation. From my knowledge there is a simple rule, If number is power of 2 and it's greater than 4, Amount of it's prime numbers shall be halved, otherwise it's equal to phi(n).
The rule above is perfectly working in my code, For example, if the input value is 8, these are the results:
phi(8) = 4
carmichael(8) = 2
But the problem is, Carmichael function is also halving other numbers for some reason, for example if input is 12, this is what my functions return:
phi(12) = 4
carmichael(12) = 4
But this is how it should look like:
phi(12) = 4
carmichael(12) = 2
Why is this happening? Perhaps non-prime odd numbers should be treated differently? Is there something that i need to add to my function?
Thank you!
First we create the gcd function to calculate greatest common divisor of 2 numbers, we will need it later in lambda function.
def gcd(a,b):
while (a>0):
b=b%a
(a,b)=(b,a)
return b
Then we look at how carmichael function works.
Let n be a positive integer. Then λ(n) is defined to be the smallest positive integer k such that
a^k≡1(mod n)
for all a such that gcd(a,n)=1.
Note that we are looking for k, the values of a is determined once we have n.
Now we initialize the function with default condition
n=int(n)
k=2
a=1
alist=[]
To find all a values we use gcd(a,n)=1 to test whether a and n have the greatest common divisor as 1, which means they are coprime.
If not, a++
if gcd(a,n)==1, we store this value to the list of a and test next a until we test all a<=n
while not ((gcd(a,n))==1):
a=a+1
while ((gcd(a,n))==1) & (a<=n) :
alist.append(a)
a=a+1
while not ((gcd(a,n))==1):
a=a+1
Ok now we have all a in the list alist, look back at definition
the smallest positive integer k such that
a^k≡1(mod n)
First we count the number of a, which is the length of alist
timer=len(alist)
Then we use
if (a**k)%n==1:
to test whether this k makes a^k≡1(mod n) for all a value in alist. We construct a loop
for a in alist:
if (a**k)%n==1:
timer=timer-1
if timer <0:
break
pass
else:
timer=len(alist)
k=k+1
to test all k number from 2, if it doesnot meet requirement, we do k=k+1
Now we have the whole function as following
def carmichael(n):
n=int(n)
k=2
a=1
alist=[]
while not ((gcd(a,n))==1):
a=a+1
while ((gcd(a,n))==1) & (a<=n) :
alist.append(a)
a=a+1
while not ((gcd(a,n))==1):
a=a+1
timer=len(alist)
while timer>=0:
for a in alist:
if (a**k)%n==1:
timer=timer-1
if timer <0:
break
pass
else:
timer=len(alist)
k=k+1
return k

Optimizing a python Code

I'm trying to optimize this code (Given two integers m, n (1 <= m <= n) we want to find all integers between m and n whose sum of squared divisors is itself a square). I'm new to coding and I'm having a hard time with this concept
def list_squared(m, n):
# your code
import math
MyList = []
for i in range(m,n):
A=[]
for k in range(1,i+1):
if i%k == 0:
A.append(k**2)
if round(math.sqrt(sum(A))) == math.sqrt(sum(A)):
B =[]
B.append(i)
B.append(sum(A))
MyList.append(B)
return MyList
import math
def list_squared(m, n):
MyList = []
for i in range(m,n):
res=0
for k in range(1,i+1):
if i%k == 0:
res+=k**2
if res == int(math.sqrt(res))**2
MyList.append(i)
return MyList
First thing that i note you can optimize is range(1,i+1). You can set initially res=1 and start the range from 2 avoiding the first cycle. The important optimization is in the end: you can stop after i/2 because there are not integer divisors after it but remember to include the dispair case (for example 3/2 = 1.5 is not a valid input for range) so wrap the result of division around ceil function. In conclusion a simple optimization is range(2, ceil(i/2)+1) with res=1

How to make perfect power algorithm more efficient?

I have the following code:
def isPP(n):
pos = [int(i) for i in range(n+1)]
pos = pos[2:] ##to ignore the trivial n** 1 == n case
y = []
for i in pos:
for it in pos:
if i** it == n:
y.append((i,it))
#return list((i,it))
#break
if len(y) <1:
return None
else:
return list(y[0])
Which works perfectly up until ~2000, since I'm storing far too much in memory. What can I do to make it work efficiently for large numbers (say, 50000 or 100000). I tried to make it end after finding one case, but my algorithm is still far too inefficient if the number is large.
Any tips?
A number n is a perfect power if there exists a b and e for which b^e = n. For instance 216 = 6^3 = 2^3 * 3^3 is a perfect power, but 72 = 2^3 * 3^2 is not.
The trick to determining if a number is a perfect power is to know that, if the number is a perfect power, then the exponent e must be less than log2 n, because if e is greater then 2^e will be greater than n. Further, it is only necessary to test prime es, because if a number is a perfect power to a composite exponent it will also be a perfect power to the prime factors of the composite component; for instance, 2^15 = 32768 = 32^3 = 8^5 is a perfect cube root and also a perfect fifth root.
The function isPerfectPower shown below tests each prime less than log2 n by first computing the integer root using Newton's method, then powering the result to check if it is equal to n. Auxiliary function primes compute a list of prime numbers by the Sieve of Eratosthenes, iroot computes the integer kth-root by Newton's method, and ilog computes the integer logarithm to base b by binary search.
def primes(n): # sieve of eratosthenes
i, p, ps, m = 0, 3, [2], n // 2
sieve = [True] * m
while p <= n:
if sieve[i]:
ps.append(p)
for j in range((p*p-3)/2, m, p):
sieve[j] = False
i, p = i+1, p+2
return ps
def iroot(k, n): # assume n > 0
u, s, k1 = n, n+1, k-1
while u < s:
s = u
u = (k1 * u + n // u ** k1) // k
return s
def ilog(b, n): # max e where b**e <= n
lo, blo, hi, bhi = 0, 1, 1, b
while bhi < n:
lo, blo, hi, bhi = hi, bhi, hi+hi, bhi*bhi
while 1 < (hi - lo):
mid = (lo + hi) // 2
bmid = blo * pow(b, (mid - lo))
if n < bmid: hi, bhi = mid, bmid
elif bmid < n: lo, blo = mid, bmid
else: return mid
if bhi == n: return hi
return lo
def isPerfectPower(n): # x if n == x ** y, or False
for p in primes(ilog(2,n)):
x = iroot(p, n)
if pow(x, p) == n: return x
return False
There is further discussion of the perfect power predicate at my blog.
IIRC, it's far easier to iteratively check "Does it have a square root? Does it have a cube root? Does it have a fourth root? ..." You will very quickly get to the point where putative roots have to be between 1 and 2, at which point you can stop.
I think a better way would be implementing this "hack":
import math
def isPP(n):
range = math.log(n)/math.log(2)
range = (int)(range)
result = []
for i in xrange(n):
if(i<=1):
continue
exponent = (int)(math.log(n)/math.log(i))
for j in [exponent-1, exponent, exponent+1]:
if i ** j == n:
result.append([i,j])
return result
print isPP(10000)
Result:
[[10,4],[100,2]]
The hack uses the fact that:
if log(a)/log(b) = c,
then power(b,c) = a
Since this calculation can be a bit off in floating points giving really approximate results, exponent is checked to the accuracy of +/- 1.
You can make necessary adjustments for handling corner cases like n=1, etc.
a relevant improvement would be:
import math
def isPP(n):
# first have a look at the length of n in binary representation
ln = int(math.log(n)/math.log(2)) + 1
y = []
for i in range(n+1):
if (i <= 1):
continue
# calculate max power
li = int(math.log(i)/math.log(2))
mxi = ln / li + 1
for it in range(mxi):
if (it <= 1):
continue
if i ** it == n:
y.append((i,it))
# break if you only need 1
if len(y) <1:
return None
else:
return list(y[0])

Python RSA Brute Force Check

I have an exercise to brute force a piece of text that has been encrypted with a very small key. The public key I have is (e = 5, n = 203). The text has been converted to ASCII, shifted a fixed number and then encrypted with the RSA public key. I have to decrypt this text using brute force only. To decrypt I'm using the simple formula of:
decrypt = (value**d)%n
Where value is the thing I want to decrypt, d being the value I am unsure of and n being the modulus.
So far I have put the numbers in a tuple called en and I loop through it like this:
for i in range(1,10):
for a in range(0,41):
ans = (en[a]**i)%203
print (chr(ans))
The first for loop is "d" the private key value I am not sure of and the second for loop is for going through the 41 length tuple. I don't have the block shift part implemented yet but I want to check if this is the correct way of brute forcing a simple RSA key.
You should try to factor n by brute force:
for i in range(n):
if n%i == 0:
print i
, from which you will find p=7 and q=29.
d = e^-1 mod phi(n)
= e^-1 mod (p-1)*(q-1)
therefore d = e^-1 mod 168, ergo d=162.
I took the liberty to improve on L3viathan's answer and provide a full working source ready to copy paste and run:
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 modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
def factor(n):
for i in range(3, n):
if n%i == 0:
return i
e = 5
n = 203
p = factor(n)
q = n//p
phi_n = (p-1) * (q-1)
# Only for python >= 3.8
# From https://docs.python.org/3/library/functions.html#pow
# If mod is present and exp is negative, base must be relatively prime to mod.
# In that case, pow(inv_base, -exp, mod) is returned, where inv_base is an inverse to base modulo mod.
# d_crack = pow(e, -1, phi_n)
# python < 3.8
d_crack = modinv(e, phi_n)
print('cracked d:', d_crack) # prints "cracked d: 101"

Categories

Resources