KEY_SIZE_IN_BITS = 2048
def Generate_RSA_Key_Pair(random_seed, key_name):
"""
This code generates an RSA Key Pair.
Inputs:
random_seed --- a random integer used to seed the random number
generator.
key_name --- a text string that is stored with the key to
identify it.
Output:
[public_key, private_key]
The public_key is of the form:
["public", key_name, modulus, encryption_exponent]
The private_key is of the form:
["private", key_name, modulus, decryption_exponent]
NOTE: The random number generator used to construct the RSA
modulus is very weak. Don't use this for anything other than
demonstration!
"""
print "Generating RSA Key Pair. This can take a little while."
sys.stdout.flush()
bit_size = KEY_SIZE_IN_BITS/2
lcg_modulus = next_prime(2^bit_size + 1)
random_seed = random_seed % lcg_modulus
if random_seed == 0:
random_seed = 5
p = 17
p_done = False
print "Finding p:",
sys.stdout.flush()
for n in range(KEY_SIZE_IN_BITS + 7):
p = p^2 % lcg_modulus
p = p+random_seed % lcg_modulus
p = next_prime(p)
while (p < 2^bit_size) or (p > 2^(bit_size+1)):
print ".",
sys.stdout.flush()
p += 2^bit_size % lcg_modulus
p = next_prime(p)
print "done"
q = 13
print "Finding q:",
sys.stdout.flush()
for n in range(KEY_SIZE_IN_BITS + 11):
q = q^2 % lcg_modulus
q = q+random_seed % lcg_modulus
q = next_prime(q)
while (q < 2^bit_size) or (q > 2^(bit_size+1)):
print ".",
sys.stdout.flush()
q += 2^bit_size % lcg_modulus
q = next_prime(q)
print "done"
"""
At this point, p and q are two somewhat randomly generated
prime numbers.
"""
RSA_modulus = p*q
CRT_modulus = (p-1)*(q-1)
e = 65537
g = gcd(e,CRT_modulus)
while not (g == 1):
e += 2
g = gcd(e,CRT_modulus)
d = e^(-1) % CRT_modulus
public_key = ["public", key_name, RSA_modulus, e]
private_key = ["private", key_name, RSA_modulus, d]
return([public_key, private_key])
def RSA_encrypt_text_message(text_message, public_key):
"""
Encrypt a *SHORT* text message with the given public key. NOTE:
the text message must be relatively short, and it may only use the
characters a-z and 0-9. So, no punctuation or spaces are allowed.
"""
if not public_key[0] == 'public':
print "Oops, that doesn't appear to be a public key!"
return(0)
try:
M = Integer(text_message,36)
except:
print "Oops, you message wasn't usable. Remember only a-z and 0-9 are allowed."
return(0)
if M > public_key[2]:
print "Oops, your message was too long!"
return(0)
print "Encrypting message for public key:", public_key[1]
C = power_mod(M,public_key[3],public_key[2])
return(C)
def RSA_decrypt_text_message(encrypted_message, private_key):
"""
Decrypts a message that has been encrypted with the RSA_encrypt_text_message()
function.
"""
if not private_key[0] == 'private':
print "Oops, that doesn't appear to be a private key!"
return(0)
M = power_mod(encrypted_message, private_key[3], private_key[2])
message = M.str(36)
return(message)