I'm currently coding a simplified RSA algorithm for a project at school but can't get it to work. 
I've based the code off of the formulae c = m^e(mod N) and (c^d)mod N. The encryption function works to produce what looks like a feasible output but when I put it into the decryption function it either doesn't return the message correctly or gives me this error: 
ValueError: chr() arg not in range(0x110000)
My code:
import random
import math
def is_prime(x):
    for i in range(2,int(math.sqrt(x))+1):
        if x % i == 0:
            return False
            break
    return  True
def gcd(a, b):
    if (b == 0):
        return a
    else:
        return gcd(b, a % b)
def generate_p_and_q(p,q):
    p_and_q = []
    p_and_q.append(p)
    p_and_q.append(q)
    return p_and_q
def generate_phi(p,q):
    p_and_q = generate_p_and_q(p,q)
    phi = (p_and_q[0] - 1)*(p_and_q[1] - 1)
    return phi
def generate_N(p,q):
    p_and_q = generate_p_and_q(p,q)
    N = (p_and_q[0])*(p_and_q[1])
    return N
def generate_e(p,q):
    phi = generate_phi(p,q)
    with open('First500Primes.txt') as f:
        lines = f.read().splitlines()
    for i in lines:
        if int(i) > 1 and int(i)< phi:
                if gcd(int(i), phi) == 1:
                    e = int(i)
                    break
    return e
def encrypt_RSA():
    encrypted = []
    message = input("Enter a message to encrypt:")
    message.lower()
    with open('First500Primes.txt') as f:
        lines = f.read().splitlines()
    valid = False
    choice = input("Do you want to: \nA: enter a key \nB: use a random key?\n")
    if choice.lower() == 'a':
        p = int(input("Enter a key - this must be a prime number between 0 and 500:"))
        q = int(input("Enter a key - this must be a prime number between 0 and 500:\n"))
        while valid != True:
            valid = is_prime(p) and is_prime(q)
            if valid == False:
                print("Your numbers were not prime!")
                p = int(input("Enter a key - this must be a prime number between 0 and 500:"))
                q = int(input("Enter a key - this must be a prime number between 0 and 500:\n"))
    else:
        x = random.randint(0, 499)
        y = random.randint(0, 499)
        p = int(lines[x])
        q = int(lines[y])
    generate_p_and_q(p,q)
    e = generate_e(p,q)
    N = generate_N(p,q)
    for char in message:
        encrypted.append((ord(char) ** e) % N)
    result = ''
    for i in encrypted:
        result = result + str(i)
    print("encrypted message: " + result)
    info = [encrypted, N, e]
    return (info)
encrypt_RSA()
def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)
def calculate_d(a,m):
    g,x,y = egcd(a,m)
    if g != 1:
        return None
    else:
        return x%m
def calculate_phi(N):
    with open('First500Primes.txt') as f:
        lines = f.read().splitlines()
    for num in lines:
        if N%int(num) == 0:
            p = int(num)
            q = N/int(num)
    phi = (p-1)*(q-1)
    return int(phi)
def decrypt_RSA():
    encrypted = encrypt_RSA()
    encrypted_message, N, e = encrypted[0], encrypted[1], encrypted[2]
    print(N)
    phi = calculate_phi(N)
    d = calculate_d(phi,e)
    print("D: " + str(d))
    message = []
    encrypted_message = (encrypted[0])
    for c in encrypted_message:
        m = (c**d) % N
        print(m)
        message.append(chr(m))
    print(message)
decrypt_RSA()
I need the code to firstly encrypt the message with the encrypt function then decrypt it with the decrypt function, so the encrypted and original message should be displayed.
Could someone tell me whats wrong with my code (since I'm still in school, it may need to be simplified), any additional feedback would be greatly appreciated.
 
    