For educational purposes, I'm trying to implement the RSA key generation and then signing a message with subsequent verification. Although, I'm following the general formulas for the key generation, eventually the verification returns False.
import hashlib
def fast_modular_exponentiation(a, b, n):
result = 1
while b > 0:
if b % 2 == 1:
result = (result * a) % n
a = (a * a) % n
b //= 2
return result
def generate_RSA_keys(p, q):
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = fast_modular_exponentiation(e, phi - 1, n)
return e, d, n
def RSA_signature_generation(message, d, n):
digest = int.from_bytes(hashlib.sha256(message).digest(), byteorder='big')
signature = fast_modular_exponentiation(digest, d, n)
return signature
def RSA_signature_verification(message, e, n, signature):
digest = int.from_bytes(hashlib.sha256(message).digest(), byteorder='big')
verification = fast_modular_exponentiation(signature, e, n) is digest
return verification
# generate RSA keys
e, d, n = generate_RSA_keys(23, 47)
# message to be signed
message = b"hello world"
# generate RSA signature
signature = RSA_signature_generation(message, d, n)
# verify RSA signature
verification = RSA_signature_verification(message, e, n, signature)
print(verification) # False
Running the code yields False instead of True.
For everybody that comes up with the same problem, thanks to the above comments I could find a working solution:
import hashlib
from Crypto.Util.number import getPrime
def fast_modular_exponentiation(a, b, n):
result = 1
while b > 0:
if b % 2 == 1:
result = (result * a) % n
a = (a * a) % n
b //= 2
return result
def extended_euclidean_algorithm(exp_encrypt, totient):
do, dn = 0, 1
r_old = totient # dont overwrite original value, keep for later
nr = exp_encrypt
while nr > 0:
q = r_old // nr # thats the quotient
do, dn = dn, do - q * dn
r_old, nr = nr, r_old - q * nr
return do % totient if r_old == 1 else None
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
def generate_RSA_keys():
# select target security
t = 2048
# select a public exponent e
e = 65537
while True:
# select a prime p of length t/2
p = getPrime(t // 2)
# select a prime q of length t/2
q = getPrime(t // 2)
# compute n = pq
n = p * q
# compute phi(n) = (p-1)(q-1)
phi = (p - 1) * (q - 1)
# check if gcd(e, phi(n)) = 1
if gcd(e, phi) == 1:
break
# compute d with the extended Euclidean algorithm
d = extended_euclidean_algorithm(e, phi)
# return the public key (e, n) and the private key (d, n)
return e, d, n
def rsa_encryption(message, e, n):
return fast_modular_exponentiation(message, e, n)
def rsa_decryption(ciphertext, d, n):
return fast_modular_exponentiation(ciphertext, d, n)
def rsa_signature_generation(message, d, n):
digest = int.from_bytes(hashlib.sha256(message).digest(), byteorder='big')
signature = fast_modular_exponentiation(digest, d, n)
return signature
def rsa_signature_verification(message, e, n, signature):
digest = int.from_bytes(hashlib.sha256(message).digest(), byteorder='big')
verification = fast_modular_exponentiation(signature, e, n) == digest
return verification
if __name__ == '__main__':
# generate RSA keys
e, d, n = generate_RSA_keys()
print(e)
print(d)
print(n)
# message to be signed
message = b"hello world"
# convert message to integer
message_int = int.from_bytes(message, byteorder='big')
# encrypt the message
ciphertext = rsa_encryption(message_int, e, n)
print(int.from_bytes(message, byteorder='big'))
print(ciphertext)
# decrypt the message
decrypted_message = rsa_decryption(ciphertext, d, n)
print(decrypted_message)
# convert the decrypted message to bytes
decrypted_message_bytes = decrypted_message.to_bytes((decrypted_message.bit_length() + 7) // 8, byteorder='big')
print(decrypted_message_bytes)
print("=========================================")
# generate the signature
signature = rsa_signature_generation(message, d, n)
print(signature)
# verify the signature
verification = rsa_signature_verification(message, e, n, signature)
print(verification)
Related
Code implements the dynamic programming solution for global pairwise alignment of two sequences. Trying to perform a semi-global alignment between the SARS-CoV-2 reference genome and the first read in the Nanopore sample. The length of the reference genome is 29903 base pairs and the length of the first Nanopore read is 1246 base pairs. When I run the following code, I get this message in my terminal:
import sys
import numpy as np
GAP = -2
MATCH = 5
MISMATCH = -3
MAXLENGTH_A = 29904
MAXLENGTH_B = 1247
# insert sequence files
A = open("SARS-CoV-2 reference genome.txt", "r")
B = open("Nanopore.txt", "r")
def max(A, B, C):
if (A >= B and A >= C):
return A
elif (B >= A and B >= C):
return B
else:
return C
def Tmax(A, B, C):
if (A > B and A > C):
return 'D'
elif (B > A and B > C):
return 'L'
else:
return 'U'
def m(p, q):
if (p == q):
return MATCH
else:
return MISMATCH
def append(st, c):
return c + "".join(i for i in st)
if __name__ == "__main__":
if (len(sys.argv) != 2):
print("Usage: align <input file>")
sys.exit()
if (not os.path.isfile(sys.argv[1])):
print("input file not found.")
sys.exit()
S = np.empty([MAXLENGTH_A, MAXLENGTH_B], dtype = int)
T = np.empty([MAXLENGTH_A, MAXLENGTH_B], dtype = str)
with open(sys.argv[1], "r") as file:
A = str(A.readline())[:-1]
B = str(B.readline())[:-1]
print("Sequence A:",A)
print("Sequence B:",B)
N = len(A)
M = len(B)
S[0][0] = 0
T[0][0] = 'D'
for i in range(0, N + 1):
S[i][0] = GAP * i
T[i][0] = 'U'
for i in range(0, M + 1):
S[0][i] = GAP * i
T[0][i] = 'L'
for i in range(1, N + 1):
for j in range(1, M + 1):
S[i][j] = max(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP)
T[i][j] = Tmax(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP)
print("The score of the alignment is :",S[N][M])
i, j = N, M
RA = RB = RM = ""
while (i != 0 or j != 0):
if (T[i][j]=='D'):
RA = append(RA,A[i-1])
RB = append(RB,B[j-1])
if (A[i-1] == B[j-1]):
RM = append(RM,'|')
else:
RM = append(RM,'*')
i -= 1
j -= 1
elif (T[i][j]=='L'):
RA = append(RA,'-')
RB = append(RB,B[j-1])
RM = append(RM,' ')
j -= 1
elif (T[i][j]=='U'):
RA = append(RA,A[i-1])
RB = append(RB,'-')
RM = append(RM,' ')
i -= 1
print(RA)
print(RM)
print(RB)
This has nothing to do with python. The error message comes this line:
if (len(sys.argv) != 2):
print("Usage: align <input file>")
The code expects to be called with exactly one argument, the input file:
align path/to/input/file
You provided a different number of arguments, probably zero.
I am trying to implement this formula in python:
This is the code I think came up with:
N = 2
S0 = 10
K = 9
T = 2
r = 0.2
import math
def combos(n, i):
return math.factorial(n) / (math.factorial(n-i)*math.factorial(i))
def binom(S0, K , T, r, N, type_ = 'call'):
dt = T/N
# u = np.exp(sigma * np.sqrt(dt))
# d = np.exp(-sigma * np.sqrt(dt))
# p = ( np.exp(r*dt) - d ) / ( u - d )
u = 1.5
d = 0.5
p = 0.2
value = 0
for i in range(N+1):
node_prob = combos(N, i)*p**i*(1-p)**(N-i)
ST = S0*(u)**i*(d)**(N-i)
print(ST)
if type_ == 'call':
value += max(ST-K,0) * node_prob
elif type_ == 'put':
value += max(K-ST, 0) * node_prob
else:
raise ValueError("type_ must be 'call' or 'put'" )
return value*(1/(1+r)**T)
binom(S0, K, T, r, N)
But when I try to calculate the option price above I don't get 4.59375 but instead get 0.3750. As you can see i don't have to calculate the u,d and p as they are given. So it my code incorrect or is the example wrong?
I am creating a basic RSA encryption program without using an RSA library that takes a secret message, converts each character in the string to its ASCII value, encrypts with a public key and concatenates the values, and then decrypts it using a private key and returns it to a string.
All with the principle of cipher = pow(plain,e,n) and plain = pow(cipher,d,n). My issue is that when the numbers get very large as I need d and n to be 16 digits minimum, the pow() function seems to result in an error in calculation that yields an ASCII value that is out of range to convert to a character. I've been struggling to figure out where I'm going wrong for days now. Any help is appreciated. Code below:
from random import randrange, getrandbits
def is_prime(n, k=128):
# Test if n is not even.
# But care, 2 is prime !
if n == 2 or n == 3:
return True
if n <= 1 or n % 2 == 0:
return False
# find r and s
s = 0
r = n - 1
while r & 1 == 0:
s += 1
r //= 2
# do k tests
for q in range(k):
a = randrange(2, n - 1)
x = pow(a, r, n)
if x != 1 and x != n - 1:
j = 1
while j < s and x != n - 1:
x = pow(x, 2, n)
if x == 1:
return False
j += 1
if x != n - 1:
return False
return True
def generate_prime_candidate(length):
# generate random bits
p = getrandbits(length)
#p = randrange(10**7,9*(10**7))
# apply a mask to set MSB and LSB to 1
p |= (1 << length - 1) | 1
return p
def generate_prime_number(length=64):
p = 4
# keep generating while the primality test fail
while not is_prime(p, 128):
p = generate_prime_candidate(length)
return p
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def generate_keypair(p, q):
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 = randrange(1,65537)
g = gcd(e, phi)
while g != 1:
e = randrange(1,65537)
g = gcd(e, phi)
d = multiplicative_inverse(e, phi)
return ((e, n), (d, n))
def multiplicative_inverse(e, phi):
d = 0
k = 1
while True:
d = (1+(k*phi))/e
if((round(d,5)%1) == 0):
return int(d)
else:
k+=1
def encrypt(m,public):
key, n = public
encrypted = ''
print("Your original message is: ", m)
result = [(ord(m[i])) for i in range(0,len(m))]
encryption = [pow(result[i],key,n) for i in range(0,len(result))]
for i in range(0,len(encryption)):
encrypted = encrypted + str(encryption[i])
#encrypted = pow(int(encrypted),key,n)
print("Your encrypted message is: ", encrypted)
#return result,encrypted
return encrypted, encryption
def decrypt(e,c,private):
key, n = private
print("Your encrypted message is: ", c)
print(e)
decryption = [pow(e[i],key,n) for i in range(0,len(e))]
print(decryption)
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
decrypted = ''.join(result)
print("Your decrypted message is: ",decrypted)
return result,decrypted
def fastpow(x,y,p):
res = 1
x = x%p
while(y>0):
if((y&1) == 1):
res = (res*x)%p
y = y>>1
x = (x*x)%p
return res
message = input("Enter your secret message: ")
p1 = generate_prime_number()
p2 = generate_prime_number()
public, private = generate_keypair(p1,p2)
print("Your public key is ", public)
print("Your private key is ", private)
encrypted,cipher = encrypt(message,public)
decrypt(cipher,encrypted,private)
Traceback:
File "<ipython-input-281-bce7c44b930c>", line 1, in <module>
runfile('C:/Users/Mervin/Downloads/group2.py', wdir='C:/Users/Mervin/Downloads')
File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/Mervin/Downloads/group2.py", line 125, in <module>
decrypt(cipher,encrypted,private)
File "C:/Users/Mervin/Downloads/group2.py", line 100, in decrypt
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
File "C:/Users/Mervin/Downloads/group2.py", line 100, in <listcomp>
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
OverflowError: Python int too large to convert to C long
Your method multiplicative_inverse is not correct. I'm not certain what you are doing in that method with the round method and floating point division, but even if you got that part correct it would be too slow anyway, requiring O(φ) steps. The usual method for computing modular multiplicative inverses is an adaptation of the extended Euclidean algorithm, which runs in O(log(φ)2) steps. Here is a straightforward mapping from the psuedocode in the Wikipedia article to python 3 code:
def multiplicative_inverse(a, n):
t, newt = 0, 1
r, newr = n, a
while newr:
quotient = r // newr
t, newt = newt, t - quotient * newt
r, newr = newr, r - quotient * newr
if r > 1:
raise ZeroDivisionError("{} is not invertible".format(a))
if t < 0:
t = t + n
return t
for the problem Ax ≡ B (MOD C) I did this, and it was okay:
def congru(a,b,c):
for i in range(0,c):
if ((a*i - b)%c)== 0 :
print(i)
Now I have to solve a system of equations, where A = ( 5x + 7y) and A= (6x + 2y),
and B= 4 and B = 12 , respectively, and C is 26.
In other words:
( 5x + 7y)≡ 4 (mod 26)
(6x + 2y)≡ 12 (mod 26)
How do I do that?
Thanks.
For the aX ≡ b (mod m) linear congruence, here is a more powerful Python solution, based on Euler's theorem, which will work well even for very large numbers:
def linear_congruence(a, b, m):
if b == 0:
return 0
if a < 0:
a = -a
b = -b
b %= m
while a > m:
a -= m
return (m * linear_congruence(m, -b, a) + b) // a
>>> linear_congruence(80484954784936, 69992716484293, 119315717514047)
>>> 45347150615590
For the X, Y system: multiply 1st equation by 2 and the 2nd one by -7, add them together and solve for X. Then substitute X and solve for Y.
This is a very fast linear congruence solver that can solve a 4096 byte number in a second. Recursion versions meet their max depth at this length:
#included if you use withstats=True, not needed otherwise
def ltrailing(N):
return len(str(bin(N))) - len(str(bin(N)).rstrip('0'))
#included if you use withstats=True, not needed otherwise
def _testx(n, b, withstats=False):
s = ltrailing(n - 1)
t = n >> s
if b == 1 or b == n - 1:
return True
else:
for j in range(0, s):
b = pow_mod(b, 2, n, withstats)
if b == n - 1:
return True
if b == 1:
return False
if withstats == True:
print(f"{n}, {b}, {s}, {t}, {j}")
if withstats == True:
print(f"{n}, {b}, {s}, {t}")
return False
def fastlinearcongruence(powx, divmodx, N, withstats=False):
x, y, z = egcditer(powx, N, withstats)
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
if x > 1:
powx//=x
divmodx//=x
N//=x
if withstats == True:
print(f"powx = {powx}, divmodx = {divmodx}, N = {N}")
x, y, z = egcditer(powx, N, withstats)
if withstats == True:
print(f"x = {x}, y = {y}, z = {z}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
return answer
def egcditer(a, b, withstats=False):
s = 0
r = b
old_s = 1
old_r = a
quotient = 0
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
while r!= 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
if b != 0:
bezout_t = quotient = (old_r - old_s * a) // b
if withstats == True:
print(f"bezout_t = {bezout_t}")
else:
bezout_t = 0
if withstats == True:
print("Bézout coefficients:", (old_s, bezout_t))
print("greatest common divisor:", old_r)
return old_r, old_s, bezout_t
To use:
In [2703]: fastlinearcongruence(63,1,1009)
Out[2703]: 993
In [2705]: fastlinearcongruence(993,1,1009)
Out[2705]: 63
Also this is 100x faster than pow when performing this pow:
pow(1009, 2**bit_length()-1, 2**bit_length())
where the answer is 273.
This is equivalent to the much faster:
In [2713]: fastlinearcongruence(1009,1,1024)
Out[2713]: 273
Solved, here's the code for it:
def congru(a0,a1,a2,b0,b1,b2,c):
for i in range(0,c):
for j in range(0,c):
if ((a0*i + a1*j) - a2)%c ==0 and ((b0*i +b1*j)-b2)%c==0:
print('x: %d y: %d' %( i, j))
If you need a congruence system you can use this code.
from functools import reduce
class CI:
"""
cX=a (mod m)
"""
def __init__(self, c, a, m):
self.c = c%m
self.a = a%m
self.m = m
def solve(self, x):
return (x*self.c)%self.m == self.a
def find(cil):
espacio = reduce(lambda acc, ci: acc*ci.m, cil, 1)+1
for x in range(0, espacio):
if reduce(lambda acc, ci: acc and ci.solve(x), cil, True):
return x
print(find([CI(3, 2, 4), CI(4, 1, 5), CI(6, 3, 9)]))
this example will solve for x
3x=2 (mod 2)
4x=1 (mod 1)
6x=3 (mod 9)
To solve linear congruence system, You should use Chinese theorem of reminders.
I wrote full code using python and AppJar (AppJar is for grafics).
And You can download it from my github profile: github profile, full code there
There You can find all the functions I used.
It is very simple and I am sure You will understand the code, although it is written in serbian language.
I was doing a previous thread question of euclidean algorithm and multiplicative inverse and then I understood that is better post the complete code and do the rigth question: I am doing python rsa implemmentation and need to fix it because it is outputting wrong results.
The code:
import fractions #gcd
def generateRSAKeys(p, q):
"Generate RSA Public and Private Keys from prime numbers p & q"
n = p * q #is used as the modulus for both the public and private keys
etf = (p - 1) * (q - 1) #Euler's totient function. etf
# Generate a number e so that gcd(n, e) = 1, start with e = 3
e = 3
while 1:
if fractions.gcd(e, etf) == 1 and 1<e and e<etf:
break
else:
e = e + 1
#e is released as the public key exponent.
# start with a number d = etf/e will be atleast 1
#e*d == 1%etf #multiplicative inverse of etf
d = (e**(etf-2)) % etf
# Return a tuple of public and private keys
return ((n,e), (n,d))
#http://en.wikipedia.org/wiki/RSA_%28algorithm%29
if __name__ == "__main__":
print "RSA Encryption algorithm...."
p = long(raw_input("Enter the value of p (prime number):"))
q = long(raw_input("Enter the value of q (prime number):"))
print "Generating public and private keys...."
(publickey, privatekey) = generateRSAKeys(p, q)
print "Public Key (n, e) =", publickey
print "Private Key (n, d) =", privatekey
n, e = publickey
n, d = privatekey
m = 34 #some message
print "0<m<n m=", m
print "0<m<n n=" , n
#then computes ciphertext c
c = (m**e)%n
print "Encrypted number using public key =", c
#recovering
m = (c**d)%n
print "Decrypted (Original) number using private key =", m