This Code runs and saves all the values in my output text file till d but does not saves my value of public_key and private_key.it is a simple code in which i am trying to replicate RSA algorithm and trying to save all the values in a text file with open.write(). Can anyone tell me where it is wrong?
It looks like this:
import random
import time
import os
max_PrimLength = 1000000000000
output_folder_name=f"output/{int(time.time()*100)}"
os.makedirs(f"{output_folder_name}")
details_file=open(f"{output_folder_name}/details.txt","a+")
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 gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def is_prime(num):
if num == 2:
return True
if num < 2 or num % 2 == 0:
return False
for n in range(3, int(num**0.5)+2, 2):
if num % n == 0:
return False
return True
def generateRandomPrim():
while(1):
ranPrime = random.randint(0,99999)
if is_prime(ranPrime):
return ranPrime
p = generateRandomPrim()
q = generateRandomPrim()
h = p*q
phi = (p-1) * (q-1)
e = random.randint(1, phi)
g = gcd(e,phi)
while g != 1:
e = random.randint(1, phi)
g = gcd(e, phi)
d = egcd(e, phi)[1]
d = d % phi
if(d < 0):
d += phi
print("First Prime Number(p): %d" % p)
details_file.write("First Prime Number(p): %d\n" % p)
print("Second Prime Number(q): %d" % q)
details_file.write("Second Prime Number(q): %d\n" % q)
print("h: %d" %h)
details_file.write("h: %d\n" %h)
print("phi(p-1)(q-1): %d" % phi)
details_file.write("phi(p-1)(q-1): %d\n" % phi)
print("e: %d" % e)
details_file.write("e: %d\n" %e)
print("d: %d" % d)
details_file.write("d: %d\n" % d)
def generate_keyPairs():
return ((e,h),(d,h))
if _name_ == 'main':
public_key,private_key = generate_keyPairs()
print("Public_Key(Traditional_RSA): ",public_key)
details_file.write("Public_Key(Traditional_RSA): \n",public_key)
print("Private_Key(Traditional_RSA): ",private_key)
details_file.write("Private_Key(Traditional_RSA): \n",private_key)
details_file.close()
Trackback Error occured:
TypeError Traceback (most recent call last)
<ipython-input-4-3018b2703be1> in <module>
144 public_key,private_key = generate_keyPairs()
145 print("Public_Key(Traditional_RSA): " ,public_key)
--> 146 details_file.write("Public_Key(Traditional_RSA): \n" ,public_key)
147 print("Private_Key(Traditional_RSA): " ,private_key)
148 details_file.write("Private_Key(Traditional_RSA): \n" ,private_key)
TypeError: write() takes exactly one argument (2 given)
The error is you are giving 2 parameters to write, use this:
...
details_file.write(f"Public_Key(Traditional_RSA): \n{public_key}")
...
details_file.write(f"Private_Key(Traditional_RSA): \n{private_key}")
also the __name__ == "__main__" is used to run the code block only when file has been run directly, i.e
> python this_file_name.py
But if you import this file to another file like:
# other_file.py
import this_file_name
and run that file:
python other_file.py
Then code block under if __name__ == "__main__": will not run.
You are giving 2 arguments to the write() function but it only expects one - the string you want to write to the file. You should format the arguments into a single strings for your last two calls to write(). Something like this:
details_file.write("Public_Key(Traditional_RSA):" + str(public_key) + "\n")
details_file.write("Private_Key(Traditional_RSA):" + str(private_key) + "\n")
Related
I have been trying to implement Miller-Rabin primality test in Python. Unfortunately there seems to be a problem on some prime numbers. Any help is appreciated.
Code:
def _isPrime(n):
if n % 2 == 0:
return False
a = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
s, d = _Apart(n) # turns it into 2^s x d
print(s, d)
basePrime = False
isPrime = True
for base in a:
if base >= n-2:
break
if isPrime == False and basePrime == False:
return False
witness = pow(base, d)
if (witness % n) == 1 or (witness % n) == (n-1):
basePrime = True
continue
else:
basePrime = False
for r in range(1, s):
witness = pow(base, pow(2, r) * d)
if (witness % n) != ( n - 1 ):
isPrime = False
return True
Test:
isPrime(17)
Expected:
True
Result:
False
I wrote a Miller Rabin test that is deterministic, no need for random numbers. This implementation is for python 3.7. In python 3.8, llinear_diophantinex can be replaced with pow(x, -1, y). Also i used gmpy2 as it's very fast, but you can just replace the gmpy2 statements with normal pow if you can't use that, and just remove the gmpy2.mpz() wrappers since those are just used to overload operators.
import gmpy2
sinn = 2110229697309202254897383305762150945330987087513434511395506048950594976569434432057019507105035289374307720719984431280856161609820548842778454256113246763860786119268583367543952735347969627478873317341364209555365064365565504232770227619462128918701942169785585423104678142850200975026619010035331023744330713985615650556129731348659986462960062760308034462660525448390420668021248422741300646552941285862310410598374242189448623917196191138254637812716211329113836605859918549332304189053950819346551095911511755911832183789503704294770046935064469435830299623205136625543859303686699678929069468518950480476841246805908501510754550017255944080874819287974625925494008373883250410775902993163965873632474224574883242826458163446781002284368017611606202344050570737818087202137703099075773680753707346415849787963446390136517016131227807076254668461445862154978026041507116570585784569893773262639243954090283224759975513502582494002154146757110676408972377044584495342170277522887809749465855954126593100747444378301829661568735873345178089061677917127496915956539418931430313218084338374827152407795095072639044306222222695685778907958272820576498682506540189586657786292950574081739269257159839589987847266550007783514316481286222515710538845836151864127815058116482680058626451349913138908040817800742009650450811565324184631847563730941344941348929727603343965091116543702880556850922077216848669966268219928808236163268726995495688157209747596437162960244538054993785127947211290438554095851924381172697827312534174244295581184309147813790451951453564726742200569263225639113681905176376701339808868274637448606821696026703034737428319530072483125495383057919894902076566679023694181381398377144302767983385253577700652358431959604517728821603076762965129019244904679015099154368058005173028200266632883632953133017055122970338782493475762548347258351148037427739052271661340801912188203749647918379812483260399614599813650518046331670764766419886619324840045611486524123102046413946014624119568013100078163986683199814025915420877588778260860713148420321896163326473203441644820182490479899368048072263481024886708136521847014624735722333931331098969321911443978386868675912141648200500219168920887757573018380579532261231821382787339600631297820996466930957801607217549420247654458172818940238337170577825003408756362106088558651381993611741503374243481167926898332728164900189941804942580426055589622673679047058619682175301326905577843405270203660160407401675700528981573327582844330828861745574031416926871562443652858767649050943181353635950301154441954046214987718582670685455252774874198771086552440702483933126644594300464549471422237478151976561680719370424626162642534252062987911763456822609569209140676822858933588602318066530038691463577379331113471591913447226829868760176810195567325921301390329055242213842898142597360121925124635965685365925901913816717677946911762631634793638450106377437599347740569467683272089859392249351406815344105961234868327316964137925419770514177021722214309784062017826024217906664090209434553785436385765927274067126192143337589109608949427467825999057058702263715338956534536892852849984934736685814891286495169007648767081688963426768409476169071460997622740467533572971356017575900999100928776382541052696124463195981888715845688808970103527288822088031150716134784735332326775370417950625124642515148342694377095213470544739900830244879573205335578256682901821773047071352497997708791157012233232529777513203024818391621220967964874173106990772425289900446640237659116713251437567138729645677868024033209183367071421651937808005637679844370347367922676824239404492688418047080583797577102267329067247758368597488680401670673861120323439239792549053895366970423259196919428554146265587250617656401028722578111927104663315250291888502226235291264834968061065817079511872899991276288365723969841290984981957389126603952133124328219936785870274843554107325931034103072894378438818494802517594594270034007832922248742746517915210656205746338575621725899098414488628833412591266637224507533934158213117522503993423240638893845121918647788013
def llinear_diophantinex(a, b, divmodx=1, x=1, y=0, offset=0, withstats=False, pow_mod_p2=False):
origa, origb = a, gmpy2.mpz(b)
r=a
q = a//b
prevq=1
if a == 1:
return 1
if withstats == True:
print(f"a = {a}, b = {b}, q = {q}, r = {r}")
while r != 0:
prevr = r
a,r,b = b, b, r
q,r = divmod(a,b)
x, y = y, x - q * y
if withstats == True:
print(f"a = {a}, b = {b}, q = {q}, r = {r}, x = {x}, y = {y}")
y = gmpy2.mpz(1 - origb*x // origa - 1)
if withstats == True:
print(f"x = {x}, y = {y}")
x,y=y,x
modx = (-abs(x)*divmodx)%origb
if withstats == True:
print(f"x = {x}, y = {y}, modx = {modx}")
if pow_mod_p2==False:
return (x*divmodx)%origb, y, modx, (origa)%origb
else:
if x < 0: return (modx*divmodx)%origb
else: return (x*divmodx)%origb
def ffs(x):
"""Returns the index, counting from 0, of the
least significant set bit in `x`.
"""
return (x&-x).bit_length()-1
def MillerRabin(arglist):
N = arglist[0]
primetest = arglist[1]
iterx = arglist[2]
powx = arglist[3]
withstats = arglist[4]
primetest = gmpy2.powmod(primetest, powx, N)
if withstats == True:
print("first: ", primetest)
if primetest == 1 or primetest == N - 1:
return True
else:
for x in range(0, iterx):
primetest = gmpy2.powmod(primetest, 2, N)
if withstats == True:
print("else: ", primetest)
if primetest == N - 1: return True
if primetest == 1: return False
return False
def sfactorint_isprime(N, withstats=False):
N = gmpy2.mpz(N)
from multiprocessing import Pool
if N <= 1: return False
if N == 2:
return True
if N % 2 == 0:
return False
if N < 2:
return False
# Add Trial Factoring here to speed up smaller factored number testing
iterx = ffs(N-1)
""" This k test is an algorithmic test builder instead of using
random numbers. The offset of k, from -2 to +2 produces pow tests
that fail or pass instead of having to use random numbers and more
iterations. All you need are those 5 numbers from k to get a
primality answer.
"""
k = llinear_diophantinex(N, 1<<N.bit_length(), pow_mod_p2=True) - 1
t = N >> iterx
tests = [k-2, k-1, k, k+1, k+2]
for primetest in range(len(tests)):
if tests[primetest] >= N:
tests[primetest] %= N
arglist = []
for primetest in range(len(tests)):
if tests[primetest] >= 2:
arglist.append([N, tests[primetest], iterx, t, withstats])
with Pool(5) as p:
s=p.map(MillerRabin, arglist)
if s.count(True) == len(arglist): return True
else: return False
return s
Recently I also tried to implement this algorithm in the deterministic form, as shown in Miller Test, and ran into the same problem. I couldn't figure out why it failed for some numbers so I decided to implement the 'complete' Miller-Rabin Test and it worked.
I should warn that it gets slow quickly as n increases. It's advised to use some numeric library like Numpy to optimize the calculations.
With some tweaks on your code it can be achieved:
import random
def _isPrime(n):
if n % 2 == 0:
return False
rounds = 40 # Determines the accuracy of the test
s, d = _Apart(n) # Turns it into 2^s x d + 1
for _ in range(rounds):
base = random.randrange(2, n-1) # Randomly selects a base
witness = pow(base, d)
if (witness % n) == 1 or (witness % n) == (n-1):
continue
for _ in range(1, s):
witness = pow(witness, 2) % n
if witness == (n-1):
break
else: # if the for-loop is not 'broken', n is not prime
return False
return True
def is_prime(n):
"""returns True if n is prime else False"""
if n < 5 or n & 1 == 0 or n % 3 == 0:
return 2 <= n <= 3
s = ((n - 1) & (1 - n)).bit_length() - 1
d = n >> s
for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
p = pow(a, d, n)
if p == 1 or p == n - 1 or a % n == 0:
continue
for _ in range(s):
p = (p * p) % n
if p == n - 1:
break
else:
return False
return True
is there away to solve this problem even the code is work prefect for encrypted and decrypted the data when they are in same file, the problem happen when i divide the code into two parts, one part encryption and second part decryption, but still i'm getting wrong decryption data even i use same public key and n value was generated in encryption part.
suppose:
data='hello'
p=23
q=19
public key=(185,437)
private key=(533,437)
when i use the public key for decryption the data is wrong!! i have also try use private same also wrong!! any suggestion !
encryption code:
import random
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def multiplicative_inverse(e, phi):
d = 0
x1 = 0
x2 = 1
y1 = 1
temp_phi = phi
while e > 0:
temp1 = temp_phi//e
temp2 = temp_phi - temp1 * e
temp_phi = e
e = temp2
x = x2- temp1* x1
y = d - temp1 * y1
x2 = x1
x1 = x
d = y1
y1 = y
if temp_phi == 1:
return d + phi
'''
Tests to see if a number is prime.
'''
def is_prime(num):
if num == 2:
return True
if num < 2 or num % 2 == 0:
return False
for n in range(3, int(num**0.5)+2, 2):
if num % n == 0:
return False
return True
def generate_keypair(p, q):
if not (is_prime(p) and is_prime(q)):
raise ValueError('Both numbers must be prime.')
elif p == q:
raise ValueError('p and q cannot be equal')
#n = pq
n = p * q
#Phi is the totient of n
phi = (p-1) * (q-1)
#Choose an integer e such that e and phi(n) are coprime
e = random.randrange(1, phi)
#Use Euclid's Algorithm to verify that e and phi(n) are comprime
g = gcd(e, phi)
while g != 1:
e = random.randrange(1, phi)
g = gcd(e, phi)
#Use Extended Euclid's Algorithm to generate the private key
d = multiplicative_inverse(e, phi)
#Return public and private keypair
#Public key is (e, n) and private key is (d, n)
return ((e, n), (d, n))
def encrypt(pk, plaintext):
#Unpack the key into it's components
key, n = pk
#Convert each letter in the plaintext to numbers based on the character using a^b mod m
cipher = [(ord(char) ** key) % n for char in plaintext]
#Return the array of bytes
return cipher
if __name__ == '__main__':
print ("RSA Encrypter/ Decrypter")
p = int(23)
q = int(19)
print ("Generating your public/private keypairs now . . .")
public, private = generate_keypair(p, q)
print ("Your public key is ", public ," and your private key is ", private)
message = str('hello')
encrypted_msg = encrypt(private, message)
print ("Your encrypted message is: ")
print (''.join(map(lambda x: str(x), encrypted_msg)))
decryption code:
def decrypt(k,pk, ciphertext):
#Unpack the key into its components
key=k
n = pk
#Generate the plaintext based on the ciphertext and key using a^b mod m
plain = [chr((ord(char) ** key) % n) for char in ciphertext]
return ''.join(plain)
if __name__ == '__main__':
'''
Detect if the script is being run directly by the user
'''
print ("RSA Encrypter/ Decrypter")
key = int(533)
n = int(437)
public=(key,n)
message = '271169420420218'
print ("Decrypting message with public key ", public ," . . .")
print ("Your message is:")
print (decrypt(key,n, message))
i'm using python 3.6 spyder
Everything I have seen shows that the proper syntax for running an exponent function from the math import is math.exp(some_num.exponent). When I attempt to run this format, the exponent is giving me an attribute error, saying it is not an int.
I have defined e = 29 and am trying to use e as the exponent.
Also n = 16637
I have also tried just using the ** operator. That allows me to use the 2 variable (mdic, e) to calculate, however when it runs the program I get an overflow error.
p = 127
q = 131
n = p * q
thetan = (p-1)*(q-1)
e = 29
if e < thetan:
if math.gcd(e, thetan) == 1 and (e > 25):
print("e = ", e)
print("gcd of ", e, " and thetan == ", math.gcd(e, thetan))
print("Public keys == ", e, ",", n)
for k in range(1,10):
d = (k * thetan + 1)/ e
if d / 1 == d // 1:
print("d (private key) == ", d)
print("k == ", k)
k = 6
d = (k * thetan + 1)/ e
print("e == ", e)
print("e*d -1 = ", (e*d -1))
m = { 50:'What is up?',
51:'You are fast!',
52:'All your trinkets belong to us.',
53:'Someone on our team thinks someone on your team are in the same class.',
54:'You are the weakest link.',
55:'Encryption is fun;',
56:'Spring is my favorite season',
57:'Enjoy your morning beverage',
58:'I am an early riser',
59:'I am not an early riser',
60:'Wake Tech is my school',
61:'CSC 120 Computing Fundamentals',
62:'Best wishes to you'
mdic = int(input("Enter an integer from the dictionary 'm' = {50 - 62}: "))
while mdic not in m:
print("Input not a valid integer within the m dictionary.")
mdic = int(input("Enter an integer from the dictionary 'm': "))
c = math.pow(mdic, e) % n
print("The encrypted text is: ", c)
m = math.pow(c, d) % n
print(m)
thank you for any guidance.
traceback for using the math.exp function protocol:
Traceback (most recent call last):
File "C:/Python Projects/Extra Credit/Extra Credit.py", line 47, in
c = math.exp(mdic.e) % n
AttributeError: 'int' object has no attribute 'e'
c = math.exp(mdic.e) % n
Here you're trying to access the e attribute of your int, mdic. Which raises the error.
You probably want:
c = math.pow(mdic, e) % n
Equivalently, let pow do the modular arithmetic for you.
c = math.pow(mdic, e, n)
math.exp(x) is for e**x - where e is Euler's constant
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)
I was reading up on cryptography, specifically RSA(https://www.khanacademy.org/computing/computer-science/cryptography/modern-crypt/v/rsa-encryption-part-4), and decided to make an example for myself. However, even though I'm pretty sure I got my variables right, I think I got my math wrong. Can someone help me find the error? I tried to put comments everywhere I thought needed an explanation. Written in Python 3.5.2
#m^phi(n) mod n == 1 where m & n dont share a common factor
#since 1^k = 1, m^(k * phi(n)) mod n == 1, too.
#since 1*m = m, m* (m^(k * phi(n)) mod n) == m
#^^^^simplifies to m^(k * phi(n) + 1) mod n == m
#b/c m^(e*d) mod n = m
#m^(e*d) mod n == m^(k * phi(n) + 1) mod n
#e*d = k * phi(n) + 1
#d = (k * phi(n) + 1)/e
from fractions import gcd
import random
i = 1
j = 1
t = 1
def is_prime(a):
return all(a % i for i in range(2, a))
while True:
p1 = random.randrange(10.00000)#gens the 1st random prime
if is_prime(p1):
if p1 == 0 or p1 == 1:
i+=1
continue
else:
print("First Random Prime Found on attempt "+str(i)+": "+str(p1))
break
i+=1
while True:
p2 = random.randrange(10.00000)#gens the 1st random prime
if is_prime(p2):
if p2 == 0 or p2 == 1:
j+=1
continue
else:
print("First Random Prime Found on attempt "+str(j)+": "+str(p2))
break
j+=1
n = p1 * p2
print("n = p1 * p2 = "+str(n))
phi_n = (p1 - 1) * (p2 - 1)#phi(n) = how many numbers below n share no factors w/ n. Given Definition of a prime, phi(any_prime_num) is always any_prime_num - 1.
print("phi_n = (p1 - 1) * (p2 - 1) = "+str(phi_n))
while True:
e = random.randrange(10)#gens the 3rd random prime
if e % 2 != 0:
if phi_n % e == 0:
k+=1
continue
else:
print("Public Random Prime(is e)Found on attempt "+str(t)+": "+str(e))
break
k = random.randrange(e)
print("num used to find d(is k): "+str(k))
d = (k * phi_n + 1)/e
print("PRIVATE key(is d): "+str(d))
#pub_key = [n, e]
#priv_key = [d, k, p1, p2, phi_n]
m = input("Type an int: ")
if gcd(int(m), n) != 1:
quit() #b/c m & n must not share a common factor(apparently)
c = (int(m)**e) % n #cipher text(nums)
print("Encrypted: "+str(c))
u = (c**d) % n #SHOULD be decrypted text(more nums)
print("Decrypted: "+str(u))
if int(m) == int(u):
print("Successful!!")
else:
print("Unsuccessful....")