RSA validate p and q keys in python, python-rsa lib - python

UPDATE
I have a program to get two public and private keys for validate those keys.
Either those key are valid or not.
We assume that our keys are valid.
(pub , privateKey) = rsa.newkeys(1024)
However I have a relation for p, q and nlen.
This is our mathematical equation for p and q:
The primes p and q shall be selected with the following constraints:
(a) (p–1) and (q–1) shall be relatively prime to the
public exponent e.
(b) The private prime factor p shall be selected and shall satisfy
(a) condition passed successfully.
But I can't understand item (b).
In the other hands we said len(p) = len(q) = nlen/2.
nlen equal to size of module in bites.
Let's talk about this condition :
This codes are definitions of p, q, d, e and nlen.
p = privkey.p
q = privkey.q
d = privkey.d
e = privkey.e
nlen = privkey.n.bit_length()
We implemented our conditions with this code :
if not sqrt(2) * (2 ** ((nlen/2) - 1)) <= p <= (2 ** (nlen/2)) - 1:
return "Invalid P prime number size"
And another conditions implemented with this following codes :
Check q len
if not sqrt(2) * (2 ** ((nlen/2) - 1)) <= q <= (2 ** (nlen/2)) - 1:
return "Invalid Q prime number size"
Above conditions didn't match and their bodies ran.
Anyway this problem is true for decryption len condition.
Second condition passes successfully.
But first throw my written error to parent class.
This my code :
if not 2 ** (nlen/2) < d < lcm(p-1, q-1):
return "Invalid decryption key"
But why ?
I think my problem related to nlen. cause everywhere i used nlen, my Tests didn't passed and failed.
I checked its values but i don't know what i can do for fixing this problem.

I think you text is wrong because both prime factors are only used for calculations of the keys and not published. the following answer will check if the keys are valid, not if they are secure:
In order to check if two keys are valid, you need to have the following values:
p and q (prime numbers selected)
n (mod-number = p * q)
key1 and key2 (public and private key)
def is_valid(p, q, key1, key2, n): # assuming p and q are actually prime
if n != p * q: # check if n is actually p * q
return False
num = (p - 1) * (q - 1)
if (key1 * key2) % num != 1: # check if keys are valid
return False
return True

This private and public keys are absolutely valid. but our conditions are true for a secure key.
We can use pycryptodome python library for increase our key tests security.
In this case we should create a key pair with those passphrases and load them with same passphrase in pycryptodome.

Related

Why is my RSA key function returning nan?

I am currently working on a project replicating RSA key generation and testing using euclidean algorithm, extended euclidean algorithm to find the modular inverse of the value.
I used the Miller-Rabin test to choose two prime numbers, p and q.
After running the code, I am able to obtain Kpub and e, however Kpr returns as nan.
Please help!
#Euclidean Algorithm func
def EucAlgo(a, b):
if a==0:
return b
return EucAlgo(b % a,a)
def ExEucAlgo(a,b):
if a==0:
return b,0,1
gcd, s1, t1 = ExEucAlgo(b%a,a)
#gcd of a,b
s = t1 - (b/a) * s1
t = s1
return gcd, s, t
def ExEucAlgo_modInverse(a,b):
gcd, s, t = ExEucAlgo(b,a)
if (gcd == 1):
i = t % a
elif (gcd !=1):
print("There is no inverse modulo for the input.")
return i
def SqMul_ModularExpo(b, exp, n):
bin_exp = bin(exp)
base = b
for i in range (3, len(bin_exp)):
base = (base ** 2) % n
if(bin_exp[i]=='1'):
i+=1
base = (base * b) %n
return base
#RSA Key generation
p=9054583561027584891319616491815785011595937977633787663340258672121877196627062461308487615739189212918799813327175451021729047602129396754172486202100997
q=10115395220079214686776355235686624745626962891667413288473649946208213820942557513105240135405981494333016032659525466362014175268953946332375459648688023
n= p * q
phi_n= (p-1) * (q-1)
e= randint(1, phi_n - 1)
while((EucAlgo(e,phi_n)) !=1):
e = randint(1, (phi_n-1))
d = ExEucAlgo_modInverse(e,phi_n)
print(f"\nKpr={d}")
print(f"\nKpub=(n={n})\n \ne={e}")
The problem is that you are using float point division which will result in returning float a point which when dealing with large int can result in very large floats which python can't handle so the solution is to use integer division which means 5//2=2 not 2.5. The problem is that Now encrypting and decrypting data would result in wrong decryption. (You wont get 2 again) because of some bugs in your functions.
FIRST: use public exponent pf 65537(prime number) which is the default for all RSA implementations(see your browser certificates) rather than finding a random one. Then after calculating the extended Euclidean algorithm which is used to find modulo inverse you dont have to make any more calculations(just return this value if GCD is 1 otherwise raise an error or whatever).
Here is the complete code that works after removing some unneeded (functions, imports, and random public exponent) READ comments.
def EucAlgo(a, b):
if a == 0:
return b
return EucAlgo(b % a, a)
def ExEucAlgo(a,b):
if a==0:
return b, 0, 1
gcd, s1, t1 = ExEucAlgo(b%a, a)
# You dont use / use // to make integer division
s = t1 - (b//a) * s1
t = s1
return gcd, s, t
def ExEucAlgo_modInverse(a,b):
gcd, s, t = ExEucAlgo(a, b)
if (gcd == 1):
# Just return s which is the inverse of public exponent
return s
elif (gcd != 1):
# I think it's better to raise an error but it's up to you
print("There is no inverse modulo for the input.")
#RSA Key generation
p = 9054583561027584891319616491815785011595937977633787663340258672121877196627062461308487615739189212918799813327175451021729047602129396754172486202100997
q = 10115395220079214686776355235686624745626962891667413288473649946208213820942557513105240135405981494333016032659525466362014175268953946332375459648688023
n = p * q
phi_n = (p-1) * (q-1)
# Just use fixed prime public exponent rather than trying fixed ones
e = 65537
d = ExEucAlgo_modInverse(e, phi_n)
print(f"\nKpr={d}")
print(f"\nKpub=(n={n})\n \ne={e}")
# Try to encrypt and decrypt 36
ciphertext = pow(36, e, n)
print("Encrypted data {}".format(ciphertext))
print("Decrypted data is {}".format(pow(ciphertext, d, n)))

How to replace zero with a small number?

I want to replace the divisor with a very small number if it equals to 0. I am doing an operation which is like:
A = pow(X,2)/(q - P)
It computes these values and stores them in an array (for looped). However, at certain places q - P = 0, which throws a runtime error. I know that there is a work around, I do not want that. How can I set q - P to a very small number in case q - P = 0 for a particular iteration.
I would recommend to use a try except block and set A to a different value if a ZeroDivisionError error occurs:
try:
A = (pow(X,2))/(q - P))
except ZeroDivisionError:
A = 99999999999 #big nuber because devision by a small number
# you can also set A to infinity with `A = np.inf`
If thats not an option for you (e.g. you really want to change q or P and not only A) you can simply add a small number to q or P
if q == P:
q+= 0.00000000000001 # or P+=small_number or q-=small_number or P-=small_number
You can use an inline if:
very_small_number = 0.001
A = pow(X, 2) / ( q - P if q != P else very_small_number )
You can use the following trick:
diff = q - P or .001
A = pow(X, 2) / diff
or
A = pow(X, 2) / (q - P or .001)

Decimal To Binary Python Getting an Extra Zero In Return String

This is for a school project. I need to create a function using recursion to convert an integer to binary string. It must be a str returned, not an int. The base case is n==0, and then 0 would need to be returned. There must be a base case like this, but this is where I think I am getting the extra 0 from (I could be wrong). I am using Python 3.6 with the IDLE and the shell to execute it.
The function works just fine, expect for this additional zero that I need gone.
Here is my function, dtobr:
def dtobr(n):
"""
(int) -> (str)
This function has the parameter n, which is a non-negative integer,
and it will return the string of 0/1's
which is the binary representation of n. No side effects.
Returns bianry string as mentioned. This is like the function
dtob (decimal to bianary) but this is using recursion.
Examples:
>>> dtob(27)
'11011'
>>> dtob(0)
'0'
>>> dtob(1)
'1'
>>> dtob(2)
'10'
"""
if n == 0:
return str(0)
return dtobr(n // 2) + str(n % 2)
This came from the function I already wrote which converted it just fine, but without recursion. For reference, I will include this code as well, but this is not what I need for this project, and there are no errors with this:
def dtob(n):
"""
(int) -> (str)
This function has the parameter n, which is a non-negative integer,
and it will return the string of 0/1's
which is the binary representation of n. No side effects.
Returns bianry string as mentioned.
Examples:
>>> dtob(27)
'11011'
>>> dtob(0)
'0'
>>> dtob(1)
'1'
>>> dtob(2)
'10'
"""
string = ""
if n == 0:
return str(0)
while n > 0:
remainder = n % 2
string = str(remainder) + string
n = n // 2
Hopefully someone can help me get ride of that additional left hand zero. Thanks!
You need to change the condition to recursively handle both the n // 2 and n % 2:
if n <= 1:
return str(n) # per #pault's suggestion, only needed str(n) instead of str(n % 2)
else:
return dtobr(n // 2) + dtobr(n % 2)
Test case:
for i in [0, 1, 2, 27]:
print(dtobr(i))
# 0
# 1
# 10
# 11011
FYI you can easily convert to binary format like so:
'{0:b}'.format(x) # where x is your number
Since there is already an answer that points and resolves the issue with recursive way, lets see some interesting ways to achieve same goal.
Lets define a generator that will give us iterative way of getting binary numbers.
def to_binary(n):
if n == 0: yield "0"
while n > 0:
yield str(n % 2)
n = n / 2
Then you can use this iterable to get decimal to binary conversion in multiple ways.
Example 1.
reduce function is used to concatenate chars received from to_binary iterable (generator).
from functools import reduce
def to_binary(n):
if n == 0: yield "0"
while n > 0:
yield str(n % 2)
n = n / 2
print reduce(lambda x, y: x+y, to_binary(0)) # 0
print reduce(lambda x, y: x+y, to_binary(15)) # 1111
print reduce(lambda x, y: x+y, to_binary(15)) # 11011
Example 2.
join takes iterable, unrolls it and joins them by ''
def to_binary(n):
if n == 0: yield "0"
while n > 0:
yield str(n % 2)
n = n / 2
print ''.join(to_binary(0)) # 0
print ''.join(to_binary(1)) # 1
print ''.join(to_binary(15)) # 1111
print ''.join(to_binary(27)) # 11011

Create an unknown number of programmatically defined variables

I have a recursive function that can produce a difficult-to-know number of expressions, each needing a new variable multiplied to it. These variables will later be removed out by calculations involving integration or residue.
How can I develop these unknown number of variables? Maybe indexed? All examples I've seen on the internet are working with an a priori known object of a definite size, e.g. "item" in How can you dynamically create variables via a while loop? or Accessing the index in Python 'for' loops
I think I can boil it down to this simple example to use in my real script:
import sympy as s
p0,p1,p2,p3,p4=s.symbols('p0 p1 p2 p3 p4')
l = [p0, p1, p2, p3, p4]
def f(n):
if n == 0:
return l[n]
elif n == 1:
return l[n]
else:
return f(n-1)*l[n]+f(n-2)
f(3) # works
f(6) # doesnt' work - need to define ahead of time the
# dummy variables l[6], l[5], ....
# even if they are just symbols for (much) later numerical evaluation.
I need this above snippet to actually generate the needed unknowns ahead of time.
I saw some mentions of pandas, but couldn't find a good example for my need, nor even sure if that was the best route. Also saw things like, "...an unknown number of lines [file]...", or "...unknown number of arguments...", but those are, seemingly, not applicable.
Indexed objects represent an abstract thing with an index taking any values, with no restriction on how large the index can be.
import sympy as s
p = s.IndexedBase("p")
def f(n):
if n == 0 or n == 1:
return p[n]
else:
return f(n-1)*p[n] + f(n-2)
print(f(7))
Output
(p[0] + p[1]*p[2])*p[3] + (((p[0] + p[1]*p[2])*p[3] + p[1])*p[4] + p[0] + p[1]*p[2])*p[5] + (((p[0] + p[1]*p[2])*p[3] + p[1])*p[4] + ((p[0] + p[1]*p[2])*p[3] + (((p[0] + p[1]*p[2])*p[3] + p[1])*p[4] + p[0] + p[1]*p[2])*p[5] + p[1])*p[6] + p[0] + p[1]*p[2])*p[7] + p[1]
As an aside, things like p0,p1,p2,p3,p4=s.symbols('p0 p1 p2 p3 p4') can be done more easily with syms = s.symbols('p0:5') or even
n = ...
syms = s.symbols('p0:{}'.format(n))
This creates individual symbols, not an indexed object, so the number n has to be known at the time of creation. But still easier than listing p0 p1 and so on.

Is secp256k1 really a field?

I know my algebra is rusty, but isn't the following an identity operation: multiplying an element of a GF by the cardinal of the field (the modulus)? I wrote a program to verify it but couldn't:
from ecpy.curves import Curve, Point # I use Python 2.7
def bin256(num):
"""binary conversion, returns a binary string, MSB first and LSB last"""
return '{:0256b}'.format(num)
def ec_multiply(P, d):
"""double-and-add algo. Index decreasing, same naming as Wikipedia:
P is a point on the curve
d is a long
returns P*d"""
Q = None
for bit in map(int, bin256(d)):
if Q is not None:
Q = Q + Q
if bit:
if Q is None:
Q = P
else:
Q = Q + P
return Q
def main():
"""Picks a random point on secp256k1 and multiply it by the modulus
of secp256k1 and print the result."""
cv = Curve.get_curve('secp256k1')
N = Point(0x65d5b8bf9ab1801c9f168d4815994ad35f1dcb6ae6c7a1a303966b677b813b00,
0xe6b865e529b8ecbf71cf966e900477d49ced5846d7662dd2dd11ccd55c0aff7f, cv)
MODULUS = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1
Q = ec_multiply(N, MODULUS)
print 'Q: %064x %064x' % (Q.x, Q.y)
if __name__ == '__main__':
main()
But I get a different point:
Q: d113d66bf911fbf026b2a3e24c96bba45ca2d2b130cbf312a36e584249153090 56cabae3704f1c5a7957cbb1d9e2f6198337c59c02b2974d32fb7501b7e287d2
I expected Q: 65d5b8bf..., e6b865e5... instead.
Any idea why multiplying by the modulus is not working in secp256k1? Thanks in advance.
Notes:
I am using the python elliptic curve library ecpy which just works, I've tested against another library (py_ecc, pure python) and I get consistent results.
The multiplication over secp256k1 uses the double-and-add algo from Wikipedia where the index is decreasing because I start from the MSB.
I use this excellent paper that explains everything about EC and how to implement them.

Categories

Resources