def multiply_ciphers(cipher1, cipher2, public_key_file):
    cipher1 = pyrsa_sq_mul.unpack_bigint(cipher1)
    cipher2 = pyrsa_sq_mul.unpack_bigint(cipher2)
    key = open(public_key_file,'r').read()
    rsakey = RSA.importKey(key)
    mult_cipher_int = (cipher1 * cipher2) % rsakey.n
    mult_cipher_str = pyrsa_sq_mul.pack_bigint(mult_cipher_int)
    return mult_cipher_str
def decrypt_RSA(private_key_file, cipher, state='sm'):
    key = open(private_key_file,'r').read()
    rsakey = RSA.importKey(key)
    if state == 'sm':
        cipher_int = pyrsa_sq_mul.unpack_bigint(cipher)
        decrypted_byte_message_int = pyrsa_sq_mul.square_multiply(cipher_int, rsakey.d, rsakey.n) 
        decrypted_byte_message_str = pyrsa_sq_mul.pack_bigint(decrypted_byte_message_int)
    elif state == 'part3':
        cipher_rsa = PKCS1_OAEP.new(rsakey)
        decrypted_byte_message_str = cipher_rsa.decrypt(cipher)
    return decrypted_byte_message_str
def encrypt_RSA(public_key_file, message, state='sm'):
    key = open(public_key_file,'r').read()
    rsakey = RSA.importKey(key)
    if state == 'sm':
        if isinstance(message, int):
            byte_message_int = message
        else:
            byte_message_int = pyrsa_sq_mul.unpack_bigint(message)
        encrypt_byte_message_int = pyrsa_sq_mul.square_multiply(byte_message_int, rsakey.e, rsakey.n) 
        encrypt_byte_message_str = pyrsa_sq_mul.pack_bigint(encrypt_byte_message_int)
    elif state == 'part3':
        cipher_rsa = PKCS1_OAEP.new(rsakey)
        encrypt_byte_message_str = cipher_rsa.encrypt(message)
    return encrypt_byte_message_str
    '''Part II: Protocol Attack'''
    print('Part II-------------')
    plain_int = 100
    print('Encrypting: {}\n'.format(plain_int))

    cipher_int = encrypt_RSA('mykey.pem.pub', plain_int)
    print('Result:\n{}\n'.format(b64encode(cipher_int)))

    attack_num = 2
    cipher_attack = encrypt_RSA('mykey.pem.pub', attack_num)
    cipher_modified = multiply_ciphers(cipher_int, cipher_attack, 'mykey.pem.pub')
    print('Modified to: {}\n'.format(b64encode(cipher_modified)))

    decrypt_cipher_modified = decrypt_RSA('mykey.pem.priv', cipher_modified)
    print('Decrypted: {}'.format(pyrsa_sq_mul.unpack_bigint(decrypt_cipher_modified)))

    '''Part III: Implementing RSA with Padding (Local testing)'''
    print('Part III-------------')
    part3_private_key, part3_public_key = generate_RSA()
    print('The public key is:\n{}\n'.format(part3_public_key))
    print('The private key is:\n{}\n'.format(part3_private_key))

    with open("mydata.txt", 'rb') as f_message_data:
        message_data = f_message_data.read()
    print('The message to encrypt is:\n{}\n'.format(message_data))

    cipher_pkcs = encrypt_RSA('part3.pem.pub', message_data, 'part3')
    print('The cipher text after encryption is:\n{}\n'.format(b64encode(cipher_pkcs)))

    decrypt_cipher_pkcs = decrypt_RSA('part3.pem.priv', cipher_pkcs, 'part3')