def attack_single_byte_xor(ciphertext):
    # a variable to keep track of the best candidate so far
    best = None
    for i in range(2**8):  # for every possible key
        # converting the key from a number to a byte
        candidate_key = i.to_bytes(1, byteorder='big')
        # the byte string we will XOR the message against is usually called the "keystream"
        keystream = candidate_key * len(ciphertext)
        candidate_message = xor(ciphertext, keystream)
        ascii_text_chars = list(range(97, 122)) + [32]
        nb_letters = sum([x in ascii_text_chars for x in candidate_message])
        # if the obtained message has more letters than any other candidate before
        if best == None or nb_letters > best['nb_letters']:
            # store the current key and message as our best candidate so far
            best = {
                "message": candidate_message,
                'nb_letters': nb_letters,
                'key': candidate_key
            }
    # if the best message is too low quality
    if best['nb_letters'] > 0.7 * len(ciphertext):
        return best
    else:
        raise InvalidMessageException('best candidate message is: %s' %
                                      best['message'])
Esempio n. 2
0
def decrypt_aes_128_cbc(ctxt, iv, key):
    result = b''
    previous_ctxt_block = iv
    blocks = split_bytes_in_blocks(ctxt, blocksize=16)

    for block in blocks:
        to_xor = decrypt_aes_128_block(block, key)
        result += xor(to_xor, previous_ctxt_block)
        assert len(result) != 0
        # for the next iteration
        previous_ctxt_block = block

    return pkcs7_strip(result)
Esempio n. 3
0
def encrypt_aes_128_cbc(msg, iv, key):
    result = b''
    previous_ctxt_block = iv
    padded_ptxt = pkcs7_padding(msg, block_size=16)
    blocks = split_bytes_in_blocks(padded_ptxt, blocksize=16)

    for block in blocks:
        to_encrypt = xor(block, previous_ctxt_block)
        new_ctxt_block = encrypt_aes_128_block(to_encrypt, key)
        result += new_ctxt_block
        # for the next iteration
        previous_ctxt_block = new_ctxt_block

    return result
Esempio n. 4
0
def hamming_distance(a, b):
    #humming distance is between two strings of equal length is the number of positions at which the corresponding
    #symbols are different. In other words, it measures the minimum number of substitutions required to change one
    #string into the other, or the minimum number of errors that could have transformed one string into the other
    return sum(bin(byte).count('1') for byte in xor(a, b))
Esempio n. 5
0
def xor_with_key(message, key):
    #form keystream, repeat as many times as needed
    keystream = key * (len(message) // len(key) + 1)
    #XOR
    ciphertext = xor(message, keystream)
    return hexlify(ciphertext)