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
Related
I have a piece of code where I am trying to export the output. I tried this, but the only problem was where and what ~str~ had to be.
with open("piStorage.txt", "w") as fp:
fp.write(~str~)
Here is my code to find ~str~
import csv
import time
start_time = time.time()
def calcPi(limit):
q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
decimal = limit
counter = 0
while counter != decimal + 1:
if 4 * q + r - t < n * t:
yield n
if counter == 0:
yield '.'
if decimal == counter:
print('')
break
counter += 1
nr = 10 * (r - n * t)
n = ((10 * (3 * q + r)) // t) - 10 * n
q *= 10
r = nr
else:
nr = (2 * q + r) * l
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
q *= k
t *= l
l += 2
k += 1
n = nn
r = nr
def main():
pi_digits = calcPi(int(input(
"Enter the number of decimals to calculate to: ")))
i = 0
for d in pi_digits:
print(d, end='')
i += 1
if i == 200:
print("")
i = 0
if __name__ == '__main__':
main()
print("--- %s seconds ---" % (time.time() - start_time))
with open("piStorage.txt", "w") as fp:
fp.write(main)
I tried using this, but it doesn't work. It came up as:
"
Traceback (most recent call last):
File "c:\Users\William\Desktop\pi.py", line 48, in <module>
fp.write(main)
TypeError: write() argument must be str, not function
"
with open("piStorage.txt", "w") as fp:
fp.write(main)
You can use contextlib.redirect_stdout.
def main():
pi_digits = calcPi(int(input(
"Enter the number of decimals to calculate to: ")))
i = 0
from contextlib import redirect_stdout
with open("piStorage.txt", "w") as fp:
with redirect_stdout(fp):
for d in pi_digits:
print(d, end='')
i += 1
if i == 200:
print("")
i = 0
fp.write(main)
Since you're using a function name without parentheses (), this refers to the function object itself.
I think you meant to call the function by using parentheses:
fp.write(main())
This will call main() and write its returned value to the file.
However in this case that still won't work, because the way you've written main(), it doesn't actually return anything.
You need to change main() so that it writes to the file directly, instead of calling print().
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)
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'm trying to write a function that would recursively hash a key for n times, alternating between sha224 and sha256. Each iteration would be hash_256(hash_224)--a hash256 for the hash224 of the key--so that it would yield n * (hash_256(hash_224)). However, I'm new to coding and can't figure out how to write a recursive function with these parameters.
import hashlib
def shasum(key, n):
key = str(key).encode('utf-8')
hash_a = hashlib.sha224(key).hexdigest().encode('utf-8'))
hash_b = hashlib.sha256(hash_a).hexdigest()
if n == 0 or 1:
return hash_b #one iteration of 256(224)
else:
return n-1
return hash_b #stuck here
Edited: now it behaves like a number generator. What's wrong?
import hashlib
n = 0
def sha480(seed):
hashed_224 = str(hashlib.sha224(seed)).encode('utf-8')
hashed_256 = hashlib.sha256(hashed_224).hexdigest()
hashed_480 = str(hashed_256)
print("hash: " + hashed_480)
def repeater(key, n):
if n == 0:
return key
seed = str(key).encode('utf-8')
while n > 0:
return sha480(repeater(seed, n-1))
repeater('what', 2)
You have no recursive calls at all. You could change it to:
def hash_a(key):
return hashlib.sha224(key).hexdigest().encode('utf-8')
def hash_b(key):
return hashlib.sha256(key).hexdigest()
def shasum(key, n):
if n == 0: # base case: 0 iterations -> return key itself
return key
key = str(key).encode('utf-8')
return hash_b(hash_a(shasum(key, n - 1))) # recursve call
A side note: n == 0 or 1 is equivalent to (n == 0) or 1 which is always true. For that pattern, use n == 0 or n == 1 or shorter n in (0, 1)
Your code is nearly correct. just some minor issues fixed as below
import hashlib
def shasum(key, n):
print ("n: " + str(n))
key = str(key).encode('utf-8')
hash_a = hashlib.sha224(key).hexdigest().encode('utf-8')
print ("hash_a: " + str(hash_a))
hash_b = hashlib.sha256(hash_a).hexdigest()
print ("hash_b: " + str(hash_b))
if n == 0:
return hash_b #one iteration of 256(224)
else:
return shasum(hash_b, n-1)
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.