I'm writing a program that will calulate the private key for a weak RSA public key. I am wondering how I would go about determining the values for p and q from the value n. Here is the Python code so far:
from Crypto.PublicKey import RSA #PyCryptoDome
import .math as cm # My own module
with open(public_keyfile, 'rb') as key: # Public Keyfile Is in PEM format
public_key = RSA.import_key(key)
n = public_key.n # N value of the public_key
e = public_key.e # E value of the public_key
p, q = get_factors_of(n) # This I don't know how to do, though there is a question that might help [see bottom]
t = cm.lcm(p-1, q-1) # Get the lowest common multiple of q and q
d = cm.mod_inverse(e, t) # Get d, the modular inverse of e % t
private_key = RSA.construct((n, e, d, p, q) # Construct the RSA private_key
The .math module referenced above:
from math import gcd
def mod_inverse(a, b):
a = a % b
for x in range(1, b):
if (a * x) % b == 1:
return x
return 1
def lcm(x, y):
return x * y // gcd(x, y)
What I need to do appears to be referenced
here but this code is in Java.
If anyone knows how to get p and q from n with python, help would be appreciated.
Many thanks, Legorooj.
Mandatory warning: if you are after performance, you will need to investigate the details of the algorithms yourself. Even "weak" public keys will take forever to crack with a simplistic algorithm (e.g. Erathostene's sieve).
That being said, sympy.ntheory.factorint() might be what you need:
from sympy.ntheory import factorint
print(factorint(54)) # {2: 1, 3: 3} i.e. 54 == 2**1 * 3**3
After lots of googling, and pdf reading, I found an algorithm that works. Here is a python implementation:
import math
def get_factors_of(num):
poss_p = math.floor(math.sqrt(num))
if poss_p % 2 == 0: # Only checks odd numbers, it reduces time by orders of magnitude
poss_p += 1
while poss_p < num:
if num % poss_p == 0:
return poss_p
poss_p += 2
This algorithm effectively finds the P/Q factors of a small RSA key. (I have tested it against a 64-bit PEM public key)
Related
I am creating a program that encrypts and decrypt data. I need to calculate the secret key but I can't work out how to change the algebra into a expression that can be used in python.
I tried using algebra but I could not figure it out.
I'm using python 3.6.1
def genkey():
p = 3 #prime 1
q = 11 #prime 2
n = p * q# pubkey part 1
z = (p-1)*(q-1)# 20
k = 7 #coprime to z and pub key part 2
#j = ?
return (n,k,j)
j should equal 3 and formula is
k * j = 1 ( mod z )
I am using pre-calculated numbers for testing
Link to site
For RSA:
I will provide some algorithms and codes from my own Bachelor Thesis
p and q, two prime numbers
n = p*q, n is the part of the public key
e or public exponent should be coprime with Euler function for n which is (p-1)(q-1) for prime numbers
Code for finding public exponent:
def find_public_key_exponent(euler_function):
"""
find_public_key_exponent(euler_function)
Finds public key exponent needed for encrypting.
Needs specific number in order to work properly.
:param euler_function: the result of euler function for two primes.
:return: public key exponent, the element of public key.
"""
e = 3
while e <= 65537:
a = euler_function
b = e
while b:
a, b = b, a % b
if a == 1:
return e
else:
e += 2
raise Exception("Cant find e!")
next we need modular multiplicative inverse of Euler function(n) and e, which equals d, our last component:
def extended_euclidean_algorithm(a, b):
"""
extended_euclidean_algorithm(a, b)
The result is the largest common divisor for a and b.
:param a: integer number
:param b: integer number
:return: the largest common divisor for a and b
"""
if a == 0:
return b, 0, 1
else:
g, y, x = extended_euclidean_algorithm(b % a, a)
return g, x - (b // a) * y, y
def modular_inverse(e, t):
"""
modular_inverse(e, t)
Counts modular multiplicative inverse for e and t.
:param e: in this case e is a public key exponent
:param t: and t is an Euler function
:return: the result of modular multiplicative inverse for e and t
"""
g, x, y = extended_euclidean_algorithm(e, t)
if g != 1:
raise Exception('Modular inverse does not exist')
else:
return x % t
Public key: (n, e)
Private key: (n, d)
Encryption: <number> * e mod n = <cryptogram>
Decryption: <cryptogram> * d mon n = <number>
There are some more restrictions so the cipher should be secure but it will work with conditions I provided.
And of course you need to find your way to get large prime numbers, read about prime testing
I created a small code for testing RSA, but when I try to decrypt a message
with keys that are 6-7 digit long, it takes a while and gives me the wrong
result.
from math import sqrt
def isPrime(n):
x = int(sqrt(n)) + 1
if n < 2:
return False`
for i in range(2, x):
if (n / i).is_integer():
return (i, False
return True
def factor(num):
hold = list()
inum = int(sqrt(num) + 1)
hold.append((1, num))
if num % 2 == 0: hold.append((2, int(num / 2)))
for i in range(3, inum, 2):
x = num / i
if x.is_integer():
hold.append((i, int(x)))
return hold
def egcd(a, b):
#Extended Euclidean Algorithm
x,y, u,v = 0,1, 1,0
while a != 0:
q, r = b//a, b%a
m, n = x-u*q, y-v*q
b,a, x,y, u,v = a,r, u,v, m,n
gcd = b
return y
def fastMod(n, e):
if e == 0:
return 1
if e % 2 == 1:
return n * fastMod(n, e - 1)
p = fastMod(n, e / 2)
return p * p
def decrypt(p, q, em):
#Uses CRT for decrypting
mp = em % p; mq = em % q;
dp = d % (p-1); dq = d % (q-1);
xp = fastMod(mp, dp) % p; xq = fastMod(mq, dq) % q
log = egcd(p, q)
cp = (p-log) if log > 0 else (p+log)
cq = cp
m = (((q*cp)*xp) + ((p*cq)*xq)) % n
return m
def encrypt(pm):
return fastMod(pm, e) % n
Is there any way to improve speed or fix any errors?
I try to decrypt a few messages I made with a key 9-10 digits long, but it takes
too long.
A lot of things need improvement, but most notably:
For RSA encryption/decryption: fastMod( ) should take the modulus as an input parameter, and reduce by the modulus each iteration. I found this code which illustrates the right way to do it.
For parameter generation: In practice, one could never use a function like your isPrime( ) to determine primality because it runs in exponential time. Instead, you should be doing Miller-Rabin / Strong pseudo prime tests, which can use fastMod( ) as a sub-routine.
By the way, you are implementing textbook RSA here, which is hugely insecure. You would need to use padding such as OAEP to have security, but you need to be very careful on how you implement that to prevent various forms of attacks (such as side channel attacks).
As for why you are getting the wrong result, it is hard to tell without seeing all of your code. Maybe you want to include a main function that generates params and tries to use them for encryption and decryption.
EDIT: I did notice this which looks suspicious: log = egcd(p, q). Not sure what you are doing here. I suggest you first compute d as the inverse of e mod (p-1)*(q-1) and verify that you are getting that correct (ie multiply d*e mod (p-1)*(q-1) and make sure the result is 1). If so, then do a fastMod( ) with d to see if it decrypts (it should). Once you get that working, then move on to making CRT work.
I'm working on a Python project which is supposed to encrypt, send and then decrypt messages with RSA. (I precise it's not a professional project)
I've written a small program to create these keys, and I thought it would work however I think there's a problem in my keys.
The keys are created this way :
def generate_integer ():
i = 0
number = ""
number += str(randrange(1,10))
while i < 1:
number += str(randrange(0,10))
i += 1
return int (number)
def generate_prime_integers ():
p = generate_integer ()
q = 0
premiers = False
while not prime:
q = generate_integer ()
prime = extended_euclide (p, q, False)
if p == q:
prime = False
return p, q
def generate_prime_with_Euler (i_Euler):
prime_with_Euler = False
while not prime_with_Euler:
e = randrange(2,100)
prime_with_Euler = extended_euclide (e, i_Euler, False)
return e
def extended_euclide (a,b,calculate_bezout):
r = a
u = 1
v = 0
r2 = b
u2 = 0
v2 = 1
quotient = 0
while r2 != 0:
q = r // r2
(r, u, v, r2, u2, v2) = (r2, u2, v2, r - q * r2, u - q * u2, v - q * v2)
prime = False
if r == 1:
prime = True
if calculate_bezout:
return u
else:
return prime
def calculate_d (e, i_Euler):
u = extended_euclide (e, i_Euler, True)
return u
def create_keys():
d = -1
while d < 0:
p, q = generate_prime_integers()
n = p*q
i_Euler = (p-1) * (q-1)
e = generate_prime_with_ Euler (i_Euler)
d = calculate_d (e, i_Euler)
return n, e, d
A few explanations : e is the encrypting exponent, d is the decrypting exponent, i_Euler is the Phi(n) function.
The function called is create_keys (), it uses all the functions above to create the 2 keys, public and private. I took the function 'extended_euclide' from Wikipedia, because I had no idea how to code the algorithm of Euclide, and modified it a bit so that it either gives me d (when I give True as third parameter) or tells if the two integers are relatively prime (when giving False).
So, the problem is : when I create my keys and try to encrypt/decrypt any value, it's not working
>>> n,e,d = create_keys()
n : 1634
e : 47
d : 293
>>> message = 64
>>> encrypted_message = pow (message, e, n)
>>> encrypted_message
1208
>>> decrypted_message = pow (encrypted_message, d, n)
>>> decrypted_message
140
Here, decrypted_message should be equal to message, that is to say, 64. Why is it not working ? Is there a problem in the creation of my keys, or is this another issue ?
Edit:
Thanks #BurningKarl I had indeed forgoten to check if p and q were prime numbers. Here's the new function which replaces generate_integer ()
def generate_prime_integer ():
prime= False
while not prime:
number= randrange (10,100)
square_root= int (sqrt (nombre))
if square_root< sqrt (nombre):
square_root+= 1
square_root+= 1
prime= True
for i in range (2, square_root):
if number % i == 0:
prime = False
return number
With that code it seems to be working properly.
Here is my comment as an answer:
When looking at the RSA Wikipedia page it states:
A user of RSA creates and then publishes a public key based on two large prime numbers, along with an auxiliary value.
So for the encryption to work prime numbers are needed while extended_euclide (p, q, False) only checks whether p and q are comprime, i.e. whether their greatest common divisor is 1.
More specifically, is the gmpy2.next_prime function good enough to find the large primes needed? Or should I be using one of the other many gmpy2.*_prp functions?
For example, is the following code good enough for finding suitable primes for encryption?
import os
import gmpy2
def random(bytez):
seed = reduce(lambda a, b: (a << 8)|ord(b), os.urandom(bytez), 0)
return gmpy2.mpz_urandomb(gmpy2.random_state(seed), bytez*8)
def find_prime(bytez=128):
p = random(bytez)|1
while not gmpy2.is_bpsw_prp(p):
p = random(bytez)|1
return p
def good_pair(p, q):
n = p*q
k = gmpy2.ceil(gmpy2.log2(n))
if abs(p - q) > 2**(k/2 - 100):
return n
return 0
def make_rsa_keypair():
p, q = find_prime(), find_prime()
n = good_pair(p, q)
while not n:
p, q = find_prime(), find_prime()
n = good_pair(p, q)
tot = n - (p + q - 1)
e = (1 << 16) + 1
d = gmpy2.invert(e, tot)
return {
'public':{
'n':n,
'e':e,
},
'private':{
'n':n,
'd':d,
}
}
UPDATE: updated the code with the suggestion.
Disclaimer: I maintain gmpy2.
I would recommend using gmpy2.is_bpsw_prp instead of gmpy2.next_prime. The BPSW test will be faster and there are no known counter-examples. The is_prime and next_prime checks used to use, and may still use, a fixed set of bases and it is possible to composites that pass a series of known tests. IIRC, someone found a composite that passed the first 17 checks. By default, 25 checks are done but it is a weakness.
I am planning to include an APR-CL provable primality test in the next release of gmpy2.
There are specific guidelines for selecting RSA primes that should be followed to prevent accidentally choosing primes that create an n that can be easily factored.
Hi I am trying to create a working RSA program, but on a very small level, I am having problems encrypting and decrypting with this code, can someone help me figure out what is wrong? I have tried doing this many different ways, but this way seems to be the right math, so I believe it might just be my lack of coding skills? Thanks
import random, math
def RandomPrime():
prime = False
while prime == False:
n = 2
while n % 2 == 0:
n = random.randint(10000, 100000)
s = math.trunc(n**0.5)
s = int(s)
x = 3
# While n doesn't exactly divide to equal 0, and x is less then the sqrt of n
while ( n % x != 0 ) and (x <= s):
x = x + 2
# if n is greater than s, it means it has run out of numbers to test, so is prime
if x > s:
prime = True
return n
def Modulus(p, q):
M = p * q
return M
def Totient(p, q):
T = ((p-1) * (q-1))
return T
def Pubkey(T):
prime = False
while prime == False:
n = 2
while n % 2 == 0:
n = random.randint(3, T)
s = math.trunc(n**0.5)
s = int(s)
x = 3
# While
while ( n % x != 0 ) and (x <= s):
x = x + 2
if x > s:
prime = True
return n
def privkey( T, n):
y = math.fmod(1, T)
d = float((y / n))
return d
# z is my encyption in this scenario
z = 8
# I generate p and q, using my random prime generator, i used low primes in
# this example just to see if it would work but it is still not showing reults
p = RandomPrime()
q = RandomPrime()
print(p, q)
#This creates the modulus
M = Modulus(p, q)
print(M)
# Eulier's totient
T = Totient(p, q)
print(T)
#Pub key creation
n = Pubkey(T)
print(n)
#Priv key creation
d = privkey(n, T)
print(d)
enc = (pow(z, n)) % M
print('enc: ', enc)
dec = (pow(enc, d)) % M
print('dec: ', dec)
Your privkey function appears wrong - I'm guessing you saw the definition of RSA's private key value as something like:
the value "e" such that e * d = 1 mod Phi(N)
However in this case, 1 mod Phi(N) does not mean The remainder when 1 is divided by Phi(N) (which appears to be the way you have translated it into code, based on your use of math.fmod(1, T), but in fact should be read more like:
the value "e" such that (e * d) mod Phi(N) = 1
This value is generally calculated using the Extended Euclidean Algorithm. An example Python implementation is here.
It's also worth noting that you seem to be defining privkey(T, n) but calling it as privkey(n, T).
Check my blog which in detail contains the implementation of the following using python:
MD5 Secure hash Algorithm RFC 1321, RSA public Key cryptography RFC 3447, OpenPGP RFC 4880
def keyGen():
''' Generate Keypair '''
i_p=randint(0,20)
i_q=randint(0,20)
# Instead of Asking the user for the prime Number which in case is not feasible,
# generate two numbers which is much highly secure as it chooses higher primes
while i_p==i_q:
continue
primes=PrimeGen(100)
p=primes[i_p]
q=primes[i_q]
#computing n=p*q as a part of the RSA Algorithm
n=p*q
#Computing lamda(n), the Carmichael's totient Function.
# In this case, the totient function is the LCM(lamda(p),lamda(q))=lamda(p-1,q-1)
# On the Contrary We can also apply the Euler's totient's Function phi(n)
# which sometimes may result larger than expected
lamda_n=int(lcm(p-1,q-1))
e=randint(1,lamda_n)
#checking the Following : whether e and lamda(n) are co-prime
while math.gcd(e,lamda_n)!=1:
e=randint(1,lamda_n)
#Determine the modular Multiplicative Inverse
d=modinv(e,lamda_n)
#return the Key Pairs
# Public Key pair : (e,n), private key pair:(d,n)
return ((e,n),(d,n))
Blog Link :Python Cryptography
Github Link : Python Cryptography