2020-04-15 23:05:03 +02:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
#program to generate rsa key pair using methods in EE-305
|
|
|
|
# Hesham Banafa
|
|
|
|
|
2020-04-16 04:07:52 +02:00
|
|
|
import math
|
2020-04-16 04:54:36 +02:00
|
|
|
import os
|
2020-04-16 11:35:42 +02:00
|
|
|
import sys
|
2020-04-15 23:05:03 +02:00
|
|
|
|
2020-04-17 04:21:58 +02:00
|
|
|
keysFolder = "keys/"
|
|
|
|
byteOrder = "little"
|
|
|
|
|
2020-04-15 23:05:03 +02:00
|
|
|
def main():
|
2020-04-16 11:35:42 +02:00
|
|
|
|
2020-04-16 17:56:04 +02:00
|
|
|
if sys.argv[1] == "gen" and len(sys.argv) == 4: ##rsa gen <keysize> <keyname>
|
|
|
|
n ,e ,d = generateKeys(int(sys.argv[2]))
|
2020-04-16 11:35:42 +02:00
|
|
|
key = (n, e, d)
|
2020-04-16 17:56:04 +02:00
|
|
|
keyFileName = sys.argv[3]
|
2020-04-16 11:35:42 +02:00
|
|
|
try:
|
|
|
|
saveKeyFile(key, keyFileName)
|
|
|
|
except IOError:
|
|
|
|
print("could not write file")
|
|
|
|
exit(1)
|
|
|
|
except Exception as ex:
|
|
|
|
print(ex)
|
|
|
|
exit(1)
|
2020-04-16 13:33:24 +02:00
|
|
|
if len(sys.argv) == 4:
|
|
|
|
if sys.argv[1] == "encrypt": ##rsa encrypt <message> <key>
|
|
|
|
msg = sys.argv[2]
|
|
|
|
keyName = sys.argv[3]
|
|
|
|
key = readKeyFile(keyName)
|
|
|
|
key_public = (key[0], key[1])
|
|
|
|
msg_encrypted = encrypt(msg, key_public)
|
|
|
|
print("Encrypted msg: ", msg_encrypted)
|
|
|
|
if sys.argv[1] == "decrypt": ##rsa decrypt <cipher> <key>
|
2020-04-16 17:56:04 +02:00
|
|
|
cipher = int(sys.argv[2])
|
2020-04-16 13:33:24 +02:00
|
|
|
key = readKeyFile(sys.argv[3])
|
2020-04-16 17:56:04 +02:00
|
|
|
#with open(fileName, "r") as cipherFile:
|
|
|
|
# cipher = int(cipherFile.readline()) ##one line may make problems later with padding
|
2020-04-16 13:33:24 +02:00
|
|
|
msg = decrypt(cipher, key[2],key[0])
|
|
|
|
print("Decrypted message: ", msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-16 04:07:52 +02:00
|
|
|
|
2020-04-16 11:35:42 +02:00
|
|
|
def generateKeys(bits=64):
|
2020-04-16 08:48:31 +02:00
|
|
|
#Primes of size 32 bit random
|
|
|
|
#resulting in a 64-bit key mod
|
2020-04-16 11:35:42 +02:00
|
|
|
p = getPrime(int(bits/2))
|
|
|
|
q = getPrime(int(bits/2))
|
2020-04-16 08:48:31 +02:00
|
|
|
n = p*q
|
2020-04-16 11:35:42 +02:00
|
|
|
#print("n: ", n)
|
2020-04-16 08:48:31 +02:00
|
|
|
print("%d bit key" % n.bit_length())
|
|
|
|
|
|
|
|
#lamda(n) = LCM(p-1, q-1)
|
|
|
|
#Since LCM(a,b) = ab/GCD(a,b)
|
|
|
|
#gcd = math.gcd(p-1, q-1)
|
|
|
|
#print("GCD: ", gcd)
|
|
|
|
#lcm = abs((p-1) * (q-1)) / gcd
|
|
|
|
#print("LCM: ", lcm)
|
|
|
|
phi = (p-1)*(q-1)
|
2020-04-16 11:35:42 +02:00
|
|
|
#print("phi: ", phi)
|
2020-04-16 08:48:31 +02:00
|
|
|
#e exponant should be 1 < e < lamda(n) and GCD(e, lamda(n)) = 1 (coprime)
|
|
|
|
# recommended value is 65,537
|
|
|
|
e = 65537
|
|
|
|
d = pow(e,-1,phi)
|
2020-04-16 11:35:42 +02:00
|
|
|
#print("d: ", d)
|
|
|
|
print("---------------------------------")
|
2020-04-17 03:38:09 +02:00
|
|
|
print("public key (%s/%s)" % (hex(n),hex(e)))
|
2020-04-16 11:35:42 +02:00
|
|
|
return n, e, d
|
2020-04-16 08:48:31 +02:00
|
|
|
|
2020-04-16 11:35:42 +02:00
|
|
|
def encrypt(message, publicKey):
|
2020-04-16 13:33:24 +02:00
|
|
|
msg_text = message
|
|
|
|
n = publicKey[0]
|
|
|
|
e = publicKey[1]
|
|
|
|
print("using n: {0}, e: {1}".format(n, e))
|
|
|
|
|
2020-04-17 04:21:58 +02:00
|
|
|
msg_number_form = int.from_bytes(msg_text.encode(), byteOrder)
|
2020-04-16 13:33:24 +02:00
|
|
|
print("Message: %s or %d" % (msg_text, msg_number_form))
|
|
|
|
|
|
|
|
msg_encrypted_number_form = pow(msg_number_form, e, n) # c = msg^e mod n
|
|
|
|
return msg_encrypted_number_form
|
2020-04-16 08:48:31 +02:00
|
|
|
|
2020-04-16 11:35:42 +02:00
|
|
|
def decrypt(cipher, privateKey, n):
|
2020-04-16 13:33:24 +02:00
|
|
|
msg_encrypted_number_form = cipher
|
|
|
|
d = privateKey
|
2020-04-17 03:38:09 +02:00
|
|
|
msg_decrypted_number_form = pow(msg_encrypted_number_form, d, n) # msg = c^d mod n
|
2020-04-16 13:33:24 +02:00
|
|
|
msg_decrypted = int(msg_decrypted_number_form)
|
2020-04-16 17:56:04 +02:00
|
|
|
try:
|
2020-04-17 04:21:58 +02:00
|
|
|
msg_decrypted = str(msg_decrypted.to_bytes(msg_decrypted.bit_length(), byteOrder).decode()).strip()
|
2020-04-16 17:56:04 +02:00
|
|
|
except UnicodeDecodeError:
|
|
|
|
print("Cant decrypt properly")
|
2020-04-16 13:33:24 +02:00
|
|
|
return msg_decrypted
|
2020-04-15 23:05:03 +02:00
|
|
|
|
|
|
|
def getPrime(bits):
|
2020-04-16 04:54:36 +02:00
|
|
|
while True:
|
2020-04-16 08:48:31 +02:00
|
|
|
#Byte order "little" or "big" does not matter here since we want a random number from os.urandom()
|
2020-04-17 04:21:58 +02:00
|
|
|
x = int.from_bytes(os.urandom(int(bits/8)), byteOrder)
|
2020-04-17 03:40:31 +02:00
|
|
|
print("trying: ", x, end="")
|
2020-04-16 04:54:36 +02:00
|
|
|
if isPrime(x):
|
2020-04-17 03:40:31 +02:00
|
|
|
print("\nprime: ", x)
|
2020-04-16 04:54:36 +02:00
|
|
|
return x
|
2020-04-17 03:40:31 +02:00
|
|
|
print("\r",end="")
|
2020-04-16 04:54:36 +02:00
|
|
|
|
2020-04-15 23:05:03 +02:00
|
|
|
|
|
|
|
def isPrime(number):
|
2020-04-16 04:07:52 +02:00
|
|
|
if number == 2:
|
|
|
|
return True
|
|
|
|
|
|
|
|
#if 2 devides number then num is not prime. pg.21
|
|
|
|
if number % 2 == 0 or number == 1:
|
|
|
|
return False
|
|
|
|
|
|
|
|
#largest integer less than or equal square root of number (K)
|
|
|
|
rootOfNum = math.sqrt(number)
|
|
|
|
K = math.floor(rootOfNum)
|
|
|
|
|
|
|
|
#Take odd D such that 1 < D <= K
|
|
|
|
#If D devides number then number is not prime. otherwise prime.
|
2020-04-16 20:51:36 +02:00
|
|
|
for D in range(1, K, 2):
|
|
|
|
if D % 2 == 0 or D == 1:
|
2020-04-16 04:07:52 +02:00
|
|
|
pass
|
|
|
|
else:
|
|
|
|
if number % D == 0 or number % 5 == 0:
|
|
|
|
return False
|
|
|
|
return True
|
2020-04-15 23:05:03 +02:00
|
|
|
|
2020-04-16 11:35:42 +02:00
|
|
|
def readKeyFile(keyName):
|
|
|
|
key = tuple()
|
2020-04-17 04:21:58 +02:00
|
|
|
with open(keysFolder+keyName, "r") as keyFile:
|
2020-04-16 11:35:42 +02:00
|
|
|
tempkey = keyFile.readlines()
|
2020-04-17 03:38:09 +02:00
|
|
|
key = (int(tempkey[0].strip(), 16), int(tempkey[1].strip(), 16), int(tempkey[2].strip(), 16))
|
2020-04-16 11:35:42 +02:00
|
|
|
return key
|
|
|
|
|
|
|
|
|
|
|
|
def saveKeyFile(key, fileName):
|
2020-04-17 04:21:58 +02:00
|
|
|
with open(keysFolder+fileName, "w") as keyFile:
|
2020-04-17 03:38:09 +02:00
|
|
|
keyFile.write("{0}\n{1}\n{2}\n".format(hex(key[0]), hex(key[1]), hex(key[2])))
|
2020-04-15 23:05:03 +02:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|