def cbc_iv_equals_key_attack():
  ciphertext = cbc_encrypt()
  BLOCK_SIZE = 16
  first_block_ciphertext = util.get_ith_block(ciphertext, 0, BLOCK_SIZE)

  constructed_ciphertext = first_block_ciphertext + bytes([0]*BLOCK_SIZE) + first_block_ciphertext + bytes([0]*BLOCK_SIZE*8)

  error, garbled_plaintext = cbc_decrypt(constructed_ciphertext)
  return util.xor(util.get_ith_block(garbled_plaintext, 0, BLOCK_SIZE), util.get_ith_block(garbled_plaintext, 2, BLOCK_SIZE))
Example #2
0
def ecb_chosen_plaintext_attack():
    #find block size
    BLOCK_SIZE = 16

    #find length of prefix
    empty_ciphertext = ecb_encrypt_surround(b'')
    fixed_ciphertext = ecb_encrypt_surround(b'A')
    current_empty_block = util.get_ith_block(empty_ciphertext, 0, BLOCK_SIZE)
    current_fixed_block = util.get_ith_block(fixed_ciphertext, 0, BLOCK_SIZE)
    i = 0
    while current_empty_block == current_fixed_block:
        i += 1
        current_empty_block = util.get_ith_block(empty_ciphertext, i,
                                                 BLOCK_SIZE)
        current_fixed_block = util.get_ith_block(fixed_ciphertext, i,
                                                 BLOCK_SIZE)

    trans_index = i

    number_of_chars = 0

    fixed_block = util.get_ith_block(
        ecb_encrypt_surround(b'A' * BLOCK_SIZE * 2), trans_index + 1,
        BLOCK_SIZE)
    for i in range(BLOCK_SIZE + 1, 2 * BLOCK_SIZE + 1):
        potential_fixed_block = util.get_ith_block(
            ecb_encrypt_surround(b'A' * i), trans_index + 1, BLOCK_SIZE)
        if potential_fixed_block == fixed_block:
            number_of_chars = i - BLOCK_SIZE
            break

    #decryption
    plaintext = b''
    length = len(ecb_encrypt_surround(b''))
    i = trans_index
    current_block = b'A' * BLOCK_SIZE
    while len(plaintext) < length:
        for j in range(BLOCK_SIZE):
            ciphertext_block = util.get_ith_block(
                ecb_encrypt_surround(b'A' * number_of_chars + b'A' *
                                     (BLOCK_SIZE - j - 1)), i + 1, BLOCK_SIZE)
            dictionary = {}
            for k in range(256):
                check_block = util.get_ith_block(
                    ecb_encrypt_surround(b'A' * number_of_chars +
                                         current_block[1:BLOCK_SIZE] +
                                         bytes([k])), trans_index + 1,
                    BLOCK_SIZE)
                dictionary[check_block] = bytes([k])

            #deals with padding issues
            if not ciphertext_block in dictionary:
                return plaintext.decode('utf-8')

            k = dictionary[ciphertext_block]
            current_block = current_block[1:BLOCK_SIZE] + k
        plaintext += current_block
        i += 1

    return plaintext.decode('utf-8')
Example #3
0
def md_hash(message):
    h = initial_state
    M = length_padding(message)
    for i in range(len(M) // BLOCK_SIZE):
        Mi = util.get_ith_block(M, i, BLOCK_SIZE)
        h = util.ecb_encrypt(Mi, util.padding(h, BLOCK_SIZE))[0:STATE_LEN]
    return binascii.hexlify(h)
def ecb_chosen_plaintext_attack():
    #first find the blocksize
    block_size = 0
    for block_size in range(5, 40):
        block_1 = util.get_ith_block(ecb_encrypt_prepend(b'A' * block_size), 0,
                                     block_size)
        block_2 = util.get_ith_block(
            ecb_encrypt_prepend(b'A' * (block_size + 1)), 0, block_size)
        if block_1 == block_2:
            break
    if block_size == 0:
        return False

    #verify that it is ECB mode
    check_ecb = analysis.detect_ECB_mode(
        ecb_encrypt_prepend(b'A' * 4 * block_size))
    if not check_ecb:
        return False

    #decryption
    plaintext = b''
    length = len(ecb_encrypt_prepend(b''))
    i = 0
    current_block = b'A' * block_size
    while len(plaintext) < length:
        for j in range(block_size):
            ciphertext_block = util.get_ith_block(
                ecb_encrypt_prepend(b'A' * (block_size - j - 1)), i,
                block_size)
            dictionary = {}
            for k in range(256):
                check_block = util.get_ith_block(
                    ecb_encrypt_prepend(current_block[1:block_size] +
                                        bytes([k])), 0, block_size)
                dictionary[check_block] = bytes([k])

            #deals with padding issues
            if not ciphertext_block in dictionary:
                return plaintext.decode("utf-8")

            k = dictionary[ciphertext_block]
            current_block = current_block[1:block_size] + k
        plaintext += current_block
        i += 1

    return plaintext.decode("utf-8")
def send_message_A(B):
    global s_A, a, p, B_A
    B_A = B
    s_A = pow(B_A, a, p)
    msg = MESSAGE
    key = hashes.SHA1(util.int_to_bytes(s_A))
    key = util.get_ith_block(key, 0, BLOCK_SIZE)
    iv = util.random_byte_string(BLOCK_SIZE)
    return (util.cbc_encrypt(msg, key, iv), iv)
def send_message_B(ciphertext, iv):
    global s_B, A_B, b, p
    s_B = pow(A_B, b, p)
    key = hashes.SHA1(util.int_to_bytes(s_B))
    key = util.get_ith_block(key, 0, BLOCK_SIZE)
    plaintext = util.cbc_decrypt(ciphertext, key, iv)
    assert plaintext == MESSAGE
    iv = util.random_byte_string(BLOCK_SIZE)
    return (util.cbc_encrypt(plaintext, key, iv), iv)
def cbc_padding_oracle_attack():
    ciphertext = cbc_encrypt_special()
    BLOCK_SIZE = 16
    num_blocks = len(ciphertext) // BLOCK_SIZE
    plaintext = b''

    current_ciphertext_block = iv

    for b in range(0, num_blocks):
        current_plaintext_block = b''
        failed = False
        wrong_g = b''
        i = 1
        while i < BLOCK_SIZE + 1:
            for g in range(256):
                if failed and i == 1 and g == wrong_g:
                    continue
                mod_cipher_block = current_ciphertext_block[:BLOCK_SIZE - i]
                guess_current_plain_block = bytes([g
                                                   ]) + current_plaintext_block
                for j in range(BLOCK_SIZE - i, BLOCK_SIZE):
                    mod_cipher_block += bytes([
                        guess_current_plain_block[j - BLOCK_SIZE + i]
                        ^ current_ciphertext_block[j] ^ i
                    ])
                trial_ciphertext = util.get_ith_block(ciphertext, b,
                                                      BLOCK_SIZE)
                try:
                    cbc_decrypt_special(trial_ciphertext, mod_cipher_block)
                    current_plaintext_block = guess_current_plain_block
                    break
                except PaddingError:
                    pass
            if len(current_plaintext_block) != i:
                failed = True
                wrong_g = current_plaintext_block[-1]
                current_plaintext_block = b''
                i -= 2
            i += 1
        plaintext += current_plaintext_block
        current_ciphertext_block = util.get_ith_block(ciphertext, b,
                                                      BLOCK_SIZE)

    return util.unpadding(plaintext)
Example #8
0
def md_hash(message, state_len = STATE_LEN, H = None):
  # initial state
  h = b''.join([util.int_to_bytes((37*i + 42) % 256) for i in range(state_len)])
  if not H:
    H = h
  M = util.padding(message, AES_BLOCK_SIZE)
  for i in range(len(M)//AES_BLOCK_SIZE):
    Mi = util.get_ith_block(M, i, AES_BLOCK_SIZE)
    H = util.ecb_encrypt(Mi, util.padding(H, AES_BLOCK_SIZE))[0:state_len]
  return binascii.hexlify(H)
Example #9
0
def get_intermediate_states(message, k):
  states = {}
  h = initial_state
  for i in range(len(message) // BLOCK_SIZE):
    block = util.get_ith_block(message, i, BLOCK_SIZE)
    h = md_hash_instrumented(block, h)

    # exclude intermediate states not in our expandable message regime
    if k <= i <= k + (1 << k) - 1:
      states[h] = i
    h = binascii.unhexlify(h)
  return states
def cbc_bitflipping_attack():
  ciphertext = cbc_encrypt_surround(b'')
  BLOCK_SIZE = 16
  num_blocks = len(ciphertext)//BLOCK_SIZE
  first_block_ciphertext = util.get_ith_block(ciphertext, 0, BLOCK_SIZE)
  second_block_plaintext = b'%20MCs;userdata='

  desired_text = util.padding(b';admin=true;', BLOCK_SIZE)
  fixed_first_block = b''

  for i in range(BLOCK_SIZE):
    fixed_first_block += bytes([second_block_plaintext[i]^first_block_ciphertext[i]^desired_text[i]])

  fixed_ciphertext = fixed_first_block + ciphertext[BLOCK_SIZE:]
  print(cbc_decrypt_surround(fixed_ciphertext))
Example #11
0
def construct_new_MAC(known_message, MAC, message_suffix, key_length=16):
    NUM_REGS = 5
    original_byte_len = key_length + len(known_message)
    original_bit_len = original_byte_len * 8

    init_regs = [
        struct.unpack('>I', util.get_ith_block(MAC, i, 4))[0]
        for i in range(NUM_REGS)
    ]

    glue_padding = b'\x80' + b'\x00' * (
        (56 - (original_byte_len + 1) % 64) % 64) + struct.pack(
            b'>Q', original_bit_len)
    new_message = known_message + glue_padding + message_suffix

    return new_message, hashes.SHA1(message_suffix,
                                    original_byte_len=key_length +
                                    len(new_message),
                                    init_state=init_regs)
def ctr_bitflipping_attack():
    ciphertext = ctr_encrypt_surround(b'')
    BLOCK_SIZE = 16
    num_blocks = len(ciphertext) // BLOCK_SIZE
    third_block_ciphertext = util.get_ith_block(ciphertext, 2, BLOCK_SIZE)
    third_block_plaintext = b';comment2=%20lik'

    desired_text = util.padding(b';admin=true;', BLOCK_SIZE)
    fixed_third_block = b''

    for i in range(BLOCK_SIZE):
        fixed_third_block += bytes([
            third_block_plaintext[i] ^ third_block_ciphertext[i]
            ^ desired_text[i]
        ])

    fixed_ciphertext = ciphertext[
        0:2 * BLOCK_SIZE] + fixed_third_block + ciphertext[3 * BLOCK_SIZE:]
    print(ctr_decrypt_surround(fixed_ciphertext))
Example #13
0
    assert '&' not in email and '=' not in email
    return {
        'email': email,
        'uid': 10,
        'role': 'user',
    }


def encrypt_profile_for(email):
    plaintext = encode_profile(profile_for(email)).encode('utf-8')
    return util.ecb_encrypt(util.padding(plaintext, 16), PROFILE_KEY)


def decrypt_profile(crypt):
    plaintext = util.ecb_decrypt(crypt, PROFILE_KEY)
    return decode_profile(util.unpadding(plaintext).decode('utf-8'))


if __name__ == '__main__':
    BLOCK_SIZE = 16
    admin = util.padding(b'admin', BLOCK_SIZE)
    admin_block = util.get_ith_block(
        encrypt_profile_for('A' * (BLOCK_SIZE - len('email=')) +
                            admin.decode('utf-8')), 1, BLOCK_SIZE)
    first_block = util.get_ith_block(encrypt_profile_for('*****@*****.**'), 0,
                                     BLOCK_SIZE)
    second_block = util.get_ith_block(encrypt_profile_for('*****@*****.**'), 1,
                                      BLOCK_SIZE)
    admin_ciphertext = first_block + second_block + admin_block
    print(decrypt_profile(admin_ciphertext))
Example #14
0
    (ciphertext, iv) = dh.send_message_A(B_B)
    (ciphertext, iv) = dh.send_message_B(ciphertext, iv)
    print('Successfully executed DH Protocol')

    # Simulate MITM Attack on DH Protocol
    # by messing with the 'g' parameter

    # g = 1
    (p, g, A_A) = dh.send_params_A()
    B_B = dh.send_params_B(p, 1, 1)
    (ciphertext, iv) = dh.send_message_A(B_B)
    (_, _) = dh.send_message_B(ciphertext, iv)

    s = 1
    key = hashes.SHA1(util.int_to_bytes(s))
    key = util.get_ith_block(key, 0, dh.BLOCK_SIZE)
    plaintext = util.cbc_decrypt(ciphertext, key, iv)
    assert plaintext == dh.MESSAGE

    # g = p
    (p, g, A_A) = dh.send_params_A()
    B_B = dh.send_params_B(p, p, 0)
    (ciphertext, iv) = dh.send_message_A(B_B)
    (_, _) = dh.send_message_B(ciphertext, iv)

    s = 0
    key = hashes.SHA1(util.int_to_bytes(s))
    key = util.get_ith_block(key, 0, dh.BLOCK_SIZE)
    plaintext = util.cbc_decrypt(ciphertext, key, iv)
    assert plaintext == dh.MESSAGE
Example #15
0
def md_hash_instrumented(M, H=initial_state):
    for i in range(len(M) // BLOCK_SIZE):
        Mi = util.get_ith_block(M, i, BLOCK_SIZE)
        H = util.ecb_encrypt(Mi, util.padding(H, BLOCK_SIZE))[0:STATE_LEN]
    return binascii.hexlify(H)
    global s_B, A_B, b, p
    s_B = pow(A_B, b, p)
    key = hashes.SHA1(util.int_to_bytes(s_B))
    key = util.get_ith_block(key, 0, BLOCK_SIZE)
    plaintext = util.cbc_decrypt(ciphertext, key, iv)
    assert plaintext == MESSAGE
    iv = util.random_byte_string(BLOCK_SIZE)
    return (util.cbc_encrypt(plaintext, key, iv), iv)


if __name__ == '__main__':
    # Simulate Diffie Hellman Protocol
    (p, g, A_A) = send_params_A()
    B_B = send_params_B(p, g, A_A)
    (ciphertext, iv) = send_message_A(B_B)
    (ciphertext, iv) = send_message_B(ciphertext, iv)
    print('Successfully executed DH Protocol')

    # Simulate MITM Attack on DH Protocol
    (p, g, A_A) = send_params_A()
    B_B = send_params_B(p, g, p)
    (ciphertext, iv) = send_message_A(p)
    (_, _) = send_message_B(ciphertext, iv)

    s = 0
    key = hashes.SHA1(util.int_to_bytes(s))
    key = util.get_ith_block(key, 0, BLOCK_SIZE)
    plaintext = util.cbc_decrypt(ciphertext, key, iv)
    assert plaintext == MESSAGE
    print('Successfully intercepted plaintext')