def decrypt_by_crt(messages, public_key):
    """
    Requires that messages is an array of tuples of the form (ciphertext_i, n_i),
    where ciphertext_i for each i is the same message message m that is
    encrypted by m^public_key mod n_i.  Attempts an attack based on the
    Chinese Remainder theorem to compute m^public_key_key mod (n_1 * n_2 * ...).
    Here the hope is that m^public_key is not large compared to (n_1 * n_2 * ...)
    so that we can recover the original message by just taking
    (ciphertext_i - n_i * k)^(1/public_key) where k is fairly small.
    Of course this attack only works if (ciphertext_i, n_i) are all
    encryptions of the same original message (with identical padding),
    encrypted with the same (small) public.
    Returns None if unable to decrypt the messages.
    """
    print("Attempting decryption using CRT")
    crt_system = [(bits_to_int(string_to_bits(message[0])), message[1])
                  for message in messages]

    crt_solution = solve_crt_system(crt_system)

    # Recover the original message by taking the public_key root
    MAX_CRT_ROOT_TRIES = 10
    for i in range(MAX_CRT_ROOT_TRIES):
        root_result = gmpy2.iroot(
            gmpy2.mpz(crt_solution[0] + crt_solution[1] * i), public_key)

        if root_result[1]:
            oaep_padded_plaintext_int = root_result[0]
            return remove_oaep_from_plaintext(oaep_padded_plaintext_int,
                                              crt_system[0][1])

    return None
Exemple #2
0
def decrypt_by_crt(messages, public_key):
    """
    Requires that messages is an array of tuples of the form (ciphertext_i, n_i),
    where ciphertext_i for each i is the same message message m that is
    encrypted by m^public_key mod n_i.  Attempts an attack based on the
    Chinese Remainder theorem to compute m^public_key_key mod (n_1 * n_2 * ...).
    Here the hope is that m^public_key is not large compared to (n_1 * n_2 * ...)
    so that we can recover the original message by just taking
    (ciphertext_i - n_i * k)^(1/public_key) where k is fairly small.
    Of course this attack only works if (ciphertext_i, n_i) are all
    encryptions of the same original message (with identical padding),
    encrypted with the same (small) public.
    Returns None if unable to decrypt the messages.
    """
    print("Attempting decryption using CRT")
    crt_system = [(bits_to_int(string_to_bits(message[0])), message[1]) for message in messages]

    crt_solution = solve_crt_system(crt_system)
    
    # Recover the original message by taking the public_key root
    MAX_CRT_ROOT_TRIES = 10
    for i in range(MAX_CRT_ROOT_TRIES):
        root_result = gmpy2.iroot(gmpy2.mpz(crt_solution[0] + crt_solution[1] * i), public_key)    
    
        if root_result[1]:
            oaep_padded_plaintext_int = root_result[0]
            return remove_oaep_from_plaintext(oaep_padded_plaintext_int, crt_system[0][1])

    return None
def aes_encode(block, key):
    block = pad_bits_append(block, len(key))
    # the pycrypto library expects the key and block in 8 bit ascii 
    # encoded strings so we have to convert from the bit array
    block = bits_to_string(block)
    key = bits_to_string(key)
    ecb = AES.new(key.encode("latin-1"), AES.MODE_ECB)
    return string_to_bits(str(ecb.encrypt(block.encode("latin-1")), encoding="latin-1"))
Exemple #4
0
def aes_encode(block, key):
    block = pad_bits_append(block, len(key))
    # the pycrypto library expects the key and block in 8 bit ascii
    # encoded strings so we have to convert from the bit array
    block = bits_to_string(block)
    key = bits_to_string(key)
    ecb = AES.new(key.encode("latin-1"), AES.MODE_ECB)
    return string_to_bits(
        str(ecb.encrypt(block.encode("latin-1")), encoding="latin-1"))
Exemple #5
0
def retrieve_plaintext(ciphertext, private_key, n):
    """
    Given the specified ciphertext string encrypted using the specified private_key
    and n value, returns the decrypted plaintext.  Removes oaep if necessary.
    """
    ciphertext_bits = pad_bits(string_to_bits(ciphertext), MESSAGE_CHARS * ASCII_BITS)
    ciphertext_int = bits_to_int(ciphertext_bits)
    padded_plaintext_int = pow(ciphertext_int, private_key, n)

    # If the message wasn't padded, we'll detect that here.
    padded_plaintext_bits = pad_bits(convert_to_bits(padded_plaintext_int), len(ciphertext_bits))
    plaintext_string = bits_to_string(padded_plaintext_bits).strip('\x00')
    if is_valid_message(plaintext_string):
        return plaintext_string
    else:
        return remove_oaep_from_plaintext(padded_plaintext_int, n)
def retrieve_plaintext(ciphertext, private_key, n):
    """
    Given the specified ciphertext string encrypted using the specified private_key
    and n value, returns the decrypted plaintext.  Removes oaep if necessary.
    """
    ciphertext_bits = pad_bits(string_to_bits(ciphertext),
                               MESSAGE_CHARS * ASCII_BITS)
    ciphertext_int = bits_to_int(ciphertext_bits)
    padded_plaintext_int = pow(ciphertext_int, private_key, n)

    # If the message wasn't padded, we'll detect that here.
    padded_plaintext_bits = pad_bits(convert_to_bits(padded_plaintext_int),
                                     len(ciphertext_bits))
    plaintext_string = bits_to_string(padded_plaintext_bits).strip('\x00')
    if is_valid_message(plaintext_string):
        return plaintext_string
    else:
        return remove_oaep_from_plaintext(padded_plaintext_int, n)
Exemple #7
0
def deliver_hint(recipient, hint_str):
    """
    Establish an encrypted session with the specified recipient
    and send hint_str.
    """
    initialization_response = initialize(recipient[0])
    session_token = initialization_response['token']

    pg = get_pg()
    p = int(pg['p'], 16)
    g = int(pg['g'], 16)

    eve_key_response_int = pow(g, X_EVE, p)
    eve_key_response = hex(eve_key_response_int)[2:]  # chop off the "0x"

    key_received_response = send_key(recipient[0], session_token,
                                     eve_key_response, "Eve")

    (ctr_key,
     ctr_nonce) = get_ctr_info(X_EVE, int(initialization_response['public'],
                                          16))

    initial_message = receive_msg(recipient[0], session_token)

    decrypted_message = counter_mode_encrypt(initial_message['msg'], ctr_key,
                                             initial_message['iv'], ctr_nonce)
    decrypted_message_str = bits_to_string(decrypted_message)
    print("decrypted_message_str", decrypted_message_str)

    hint_hex = hex(bits_to_int(string_to_bits(hint_str)))[2:]
    encrypted_hint = counter_mode_encrypt(hint_hex, ctr_key,
                                          initial_message['iv'], ctr_nonce)
    encrypted_hint_hex = hex(bits_to_int(encrypted_hint))[2:]

    response = send_msg(recipient[0], session_token, encrypted_hint_hex,
                        initial_message['iv'])

    decrypted_message = counter_mode_encrypt(response['reply']['msg'], ctr_key,
                                             response['reply']['iv'],
                                             ctr_nonce)
    decrypted_message_str = bits_to_string(decrypted_message)
    print("decrypted_message_str", decrypted_message_str)
Exemple #8
0
def decrypt_by_public_key_root(public_key, n, ciphertext):
    ciphertext_bits = string_to_bits(ciphertext)
    ciphertext_int = bits_to_int(ciphertext_bits)
    
    PUBLIC_KEY_ROOT_ATTEMPTS = 10
    for i in range(PUBLIC_KEY_ROOT_ATTEMPTS):
        plaintext_root_result = gmpy2.iroot(gmpy2.mpz(ciphertext_int + i * n), public_key)
        if plaintext_root_result[1]:
            plaintext_int = int(plaintext_root_result[0])
            assert pow(plaintext_int, public_key) == ciphertext_int + i * n              
            print("Found integer root of message")
                
            plaintext_bits = pad_bits(convert_to_bits(plaintext_int), MESSAGE_CHARS * ASCII_BITS)
            plaintext_string = bits_to_string(plaintext_bits).strip('\x00')

            assert is_valid_message(plaintext_string)
            return plaintext_string
        else:
            print("Root result is non-integer")

    print("Unable to decrypt by taking private key root")
    return None
def deliver_hint(recipient, hint_str):
    """
    Establish an encrypted session with the specified recipient
    and send hint_str.
    """
    initialization_response = initialize(recipient[0])
    session_token = initialization_response['token']
    
    pg = get_pg()
    p = int(pg['p'], 16)
    g = int(pg['g'], 16)

    eve_key_response_int = pow(g, X_EVE, p)
    eve_key_response = hex(eve_key_response_int)[2:] # chop off the "0x"
    
    key_received_response = send_key(recipient[0], session_token,
            eve_key_response, "Eve")
    
    (ctr_key, ctr_nonce) = get_ctr_info(X_EVE, int(initialization_response['public'], 16))
    
    initial_message = receive_msg(recipient[0], session_token)
    
    
    decrypted_message = counter_mode_encrypt(initial_message['msg'], ctr_key, initial_message['iv'], ctr_nonce)
    decrypted_message_str = bits_to_string(decrypted_message)
    print("decrypted_message_str", decrypted_message_str)
    
    hint_hex = hex(bits_to_int(string_to_bits(hint_str)))[2:]
    encrypted_hint = counter_mode_encrypt(hint_hex, ctr_key, initial_message['iv'], ctr_nonce)
    encrypted_hint_hex = hex(bits_to_int(encrypted_hint))[2:]
    
    response = send_msg(recipient[0], session_token,
            encrypted_hint_hex, initial_message['iv'])
    
    decrypted_message = counter_mode_encrypt(response['reply']['msg'], ctr_key, response['reply']['iv'], ctr_nonce)
    decrypted_message_str = bits_to_string(decrypted_message)
    print("decrypted_message_str", decrypted_message_str)
Exemple #10
0
def decrypt_by_public_key_root(public_key, n, ciphertext):
    ciphertext_bits = string_to_bits(ciphertext)
    ciphertext_int = bits_to_int(ciphertext_bits)

    PUBLIC_KEY_ROOT_ATTEMPTS = 10
    for i in range(PUBLIC_KEY_ROOT_ATTEMPTS):
        plaintext_root_result = gmpy2.iroot(gmpy2.mpz(ciphertext_int + i * n),
                                            public_key)
        if plaintext_root_result[1]:
            plaintext_int = int(plaintext_root_result[0])
            assert pow(plaintext_int, public_key) == ciphertext_int + i * n
            print("Found integer root of message")

            plaintext_bits = pad_bits(convert_to_bits(plaintext_int),
                                      MESSAGE_CHARS * ASCII_BITS)
            plaintext_string = bits_to_string(plaintext_bits).strip('\x00')

            assert is_valid_message(plaintext_string)
            return plaintext_string
        else:
            print("Root result is non-integer")

    print("Unable to decrypt by taking private key root")
    return None
def create_bill_message(i, bill_amount, nonce):
    bill = create_bill(i, bill_amount)

    bill_int = bits_to_int(string_to_bits(bill))
    t = blind_msg(bill_int, nonce, BANK_PUBLIC_KEY[0], BANK_PUBLIC_KEY[1])
    return t
Exemple #12
0
def create_bill_message(i, bill_amount, nonce):
    bill = create_bill(i, bill_amount)

    bill_int = bits_to_int(string_to_bits(bill))
    t = blind_msg(bill_int, nonce, BANK_PUBLIC_KEY[0], BANK_PUBLIC_KEY[1])
    return t
Exemple #13
0
def hash(input_, length):
    h = sha512(bits_to_string(input_)).digest()
    return string_to_bits(h)[:length]
Exemple #14
0
# http://forums.udacity.com/cs387-april2012/questions/2814/hw4-6-challenge-question-discussion
#
# If you want to use functions from unit4_util, make sure to set the ASCII_BITS = 8
# import unit4_util
# unit4_util.ASCII_BITS = 8
#
# unit4_util code: http://pastebin.com/Te2AmDre

from unit4_util import bits_to_int, string_to_bits, bits_to_string, convert_to_bits, pad_bits


################
e0 = 65537
n0 = 116436872704204817262873499608558046190724591466716177557829773662807162485791977636521167560986434993048860346504247233074117974671540999410485959711510256117299326339754889488213509449940603119123994148576130959569697235313003024809821145961963221161561975123663333322412762102191502543834949106445222007561
cipher0 = "<\xad\xdd\xedg\x8b\x12\x0b\x00y\xa2\xf0\x86\xcbF\xf0\x8f\xb4~\xbd\x04\xd9\xac6iwxk\xcfi\xc4Z1p\\\x14\xa4rL\x9a#\x9f\xbf~\xec[\x8d\xfc(\x82\xc2s\xb9\x0e\xec(\xd9.}\xc5\xdf\xa8'`\xa5\xdb\x18\xf1Z\xff\x82xQJa\x11\x98/x&{\x0b\x17\xb9\xb1\x88\x8f\x85B\x7fH\xdbX\x9aV\x9a\xaf\x0fKc+\xf7?\xb8\xb4\x1fo\x0eeI\xa9\x90\x11\x83\xb8\xfdaMwM\xc7\xb48&-\xe8\xf1C"
c0 = bits_to_int(string_to_bits(cipher0))
m0 = ''#YOUR ANSWER HERE
################

################
e1 = 3
n1 = 131776503472993446247578652375782286463851826883886018427615607890323792437218636575447994626809806013420405963813337101556738852432247872506699457038044621191649758706817663135648397013226104530751563478671698441687437700125203966101608457556637550910814187779205610883544935666685906870199595346450733709263
cipher1 = '\x04\xacq#E/\xf4X\x126\xef\xc6\xb1\xfc\x10p*\x98P\xde\x089K\x16y0\xfa\xde\x9f\x05\x15+\xa3\x0f\xbc3\xd1t\xe7\x9a\x1b\x04m\xa1\x12\x96\x18Y\xf9\xc95\xce\x19 E\xfa\xe1\xb5\x8a\xd5\xf2\x99\xa6"<\xcb\x1a\xd0\xce=\x91\xfbw\t\xb5'
c1 = bits_to_int(string_to_bits(cipher1))
m1 = 'Chinese Remainder Theorem'#YOUR ANSWER HERE
################

################
e2 = 3
n2 = 65659232975830381768328338666607829001259240689809015666589078261348261561917417083788447204534665997091584936794919521220643455263371034991817572752104164283083678838816431044389236958346474896965382016943200300407371205608596328649170408446414718769422147103617311701247139971805834487439320773304455320217
cipher2 = '\x04\xe97r\x13\x99\xf7\x80m\x19\xe3f\x1a\x92]u!\x17\xdf\xa8\xfd\xd4\xd0\xbea\xe8\x1f\xefc\xd6\xc7\xbf\xce\xa4q\xfe\xa4S\xff\xaf\x1aX\xc13g\xeb\x12\xadw\x17T\x05\x1c\x8e\xd8\xea\x1bkc\xd3\xfctQt\x8e\xf6d\x1a\x98\xbc}\x08\x1d%\xc7\xd2K\xb4\xa8\x96\xcf\x98D\x8a\xbd\xa7\xd2\xcc\x861$\xd1\x1b\xdd\xa0h\x83\xdan\xcbm\xa4\xf9\xef\x96\x12\x9c|\xc9\xd7\t\x9b\x0f:\x9e\xe0\xa1\xb2\t\x8b\x9d\x18\x07\x8e]\x8c\x13\xa2'
Exemple #15
0
import lfsr
import binascii
import unit4_util

given_prng = [0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0]

def xor(word1, word2):
    key = []
    for i in xrange(0, len(word1)):
        key.append(word1[i] ^ word2[i])
    return key

message = '8d801f00c7554d3980b0c4f400c1ebc572d86f57f48d322b8e7c3a1f01c531dbe772b77be5acd34bf1979b70089615ace253c4b01350f36f82215f164b7934fdd48a30'
m_bytes = binascii.unhexlify(message)
message_bits = unit4_util.string_to_bits(m_bytes)

# Use LFSR_A51_1 to generate another 200 bits for the PRNG
lfsr = lfsr.LFSR_A51_1(given_prng[1000-19:])
new_prng = given_prng[0:1000-19]
for _ in range(0, 2000):
    new_prng.append(lfsr.next_output_bit())

# Loop through each 2000 bit range of the PRNG and use it to try and decrypt the
# message. Examine each output message visually to find the interesting one
# (which is message 1000 incidentally)
for i in range(0, 2000):
    otp = new_prng[i:len(message_bits) + i]
    plaintext = xor(message_bits, otp)
    print i, unit4_util.bits_to_string(plaintext)
Exemple #16
0
def hash(input_, length):
    input_string = bits_to_string(input_).encode(encoding='latin-1')
    h = sha512(input_string).digest()
    return string_to_bits(h)[:length]
Exemple #17
0
def oaep_pad(message, nonce, g, h):
    mm = message + [0] * (g - len(message))
    G = xor(mm, hash(nonce, g))
    H = xor(nonce, hash(G, h))
    return G + H
    
def encrypt(message, n, public_key, nonce, g, h):
    oaep = oaep_pad(message, nonce, g, h)
    m_int = bits_to_int(oaep)
    return convert_to_bits(pow(m_int, public_key, n))

##################
# ciphertext was created by calling
# `encrypt` where message and nonce are secret

ciphertext = string_to_bits("\x98WRQ5\xf4\xe5L$a\xf4\xbf\xecV\\\xb1\xe4\x18\xf1It\x01\xca\xdc\xd0@\xc8\xf6\x97\xf9K\xb8\x1b\x9a\x17\x89\xa9\xcap\x9a\xb5\xb4\x12\xf6\x01\x9avd\xedc*\xcbELRi\xf7.?\x82H\xd3Ci\xd7\xaea7\xbc\x00+\xf04\x13>\xe6q\xf3\xedg\xc4VWB\x8a\x9f\xdf%-8\xf3\x08\xc59\x84\xec\xf8G\xbe\xd2Ub\xf9K4\xa0\xa4(\xeaI\x19T\x1fM\xa6+\x81\xb0\x8d\x04\x99<%o3C-\xc6")

plaintext = "Where is the ANY key? -Homer Simpson" # YOUR ANSWER HERE

def decrypt(ciphertext, n, private_key, g, h):
    """
    Decrypts the specified ciphertext.
    Assumes that ciphertext was obtained by applying OAEP padding to a message
    (using parameters g and h), and then RSA-encrypted with parameter n and public
    key corresponding to the specified private_key.
    """
    ciphertext_int = bits_to_int(ciphertext)
    plaintext_int = pow(ciphertext_int, private_key, n)
    return decode_oaep(plaintext_int + n, g, h)
    
def decode_oaep(oaep_padded_int, g, h):