Ejemplo n.º 1
0
def cbc_encrypt(msg, key, iv):

    # check that msg == hex, key == hex, iv == hex
    # I should probably handle these better but whatever
    assert int(msg, 16)
    assert int(key, 16)
    assert int(iv, 16)

    padded_msg = pkcs7_pad(msg, block_size)
    msg_blocks = [
        padded_msg[i:(i + block_size * 2)]
        for i in range(0, len(padded_msg), block_size * 2)
    ]

    iv_first_block = xor_hex_strings(iv, msg_blocks[0])

    (block_0,
     encryptor) = aes_ecb_encrypt_with_key(bytes.fromhex(iv_first_block),
                                           bytes.fromhex(key))
    block_i = block_0
    ctext = [block_i.hex()]
    for msg_block in msg_blocks:
        iv_i = xor_hex_strings(block_i.hex(), msg_block)
        (block_i,
         encryptor) = aes_ecb_encrypt_with_key(bytes.fromhex(iv_i),
                                               bytes.fromhex(key))
        ctext.append(block_i.hex())

    return ''.join(ctext)
Ejemplo n.º 2
0
def hamming_distance(str1, str2):
    assert (len(str1) == len(str2))
    hex_str1 = str1.hex()
    hex_str2 = str2.hex()
    # can find hamming distance by just xoring and counting number of 1s in xord result
    xor_strings = xor_hex_strings(hex_str1, hex_str2)
    num_ones = sum([1 for c in bin(int(xor_strings, 16))[2:] if c == '1'])

    return num_ones
Ejemplo n.º 3
0
def hmac_sha1(key, msg):

    assert type(msg) == bytes
    assert type(key) == bytes

    if len(key) > 64:
        key = sha1(key, len(key) * 8)
    if len(key) < 64:
        key += b'\x00' * (64 - len(key))

    o_key_pad = bytes.fromhex(xor_hex_strings(key.hex(), (b'\x5c' * 64).hex()))
    i_key_pad = bytes.fromhex(xor_hex_strings(key.hex(), (b'\x36' * 64).hex()))

    i_pad_hash = bytes.fromhex(
        sha1(i_key_pad + msg,
             len(i_key_pad + msg) * 8)[2:])

    return sha1(o_key_pad + i_pad_hash, len(o_key_pad + i_pad_hash) * 8)[2:]
Ejemplo n.º 4
0
def encrypt(key, msg):

    init_seed(key)
    keystream = ''

    while len(keystream) < len(msg):
        keystream += format(extract_number(), '08x')

    keystream = keystream[:len(msg)]
    return xor_hex_strings(keystream, msg)
Ejemplo n.º 5
0
def xor_single_byte(hex_str):
    best_score = -1000
    best_string = ''
    key_byte = 0
    for i in range(0, 256):
        decrypted = xor_hex_strings(hex_str,
                                    (int(len(hex_str) / 2) * bytes([i])).hex())
        if len(decrypted) % 2: decrypted = '0' + decrypted
        temp_score = score_string(binascii.unhexlify(decrypted))

        if temp_score > best_score:
            best_score = temp_score
            best_string = codecs.decode(decrypted, 'hex')
            key_byte = i

    return (best_string, best_score, key_byte)
Ejemplo n.º 6
0
def aes_ctr_operation(key, data, nonce):
    ctr_output = ''
    ctr = 0
    block = data[ctr*32:(ctr+1)*32]

    while block:
        ctr_data = pack('<QQ', int(nonce, 16), ctr)      # see struct library for packing formatting
        aes_out = aes_ecb_encrypt_with_key(ctr_data, bytes.fromhex(key))

        temp_output = xor_hex_strings(aes_out[0].hex()[:len(block)], block)
        if len(temp_output) % 2: temp_output = '0' + temp_output

        ctr_output += temp_output

        ctr += 1
        block = data[ctr*32:(ctr+1)*32]

    return ctr_output
Ejemplo n.º 7
0
def cbc_decrypt(ciphertext, key, iv):
    ctext_blocks = [
        ciphertext[i:(i + block_size * 2)]
        for i in range(0, len(ciphertext), block_size * 2)
    ]

    CipherObj = Cipher(algorithms.AES(bytes.fromhex(key)),
                       modes.ECB(),
                       backend=default_backend())
    iv_i = iv

    decrypted_text = []
    for ctext in ctext_blocks:
        d_i = aes_ecb_decrypt(CipherObj, bytes.fromhex(ctext)).hex()
        decrypted_text.append(xor_hex_strings(iv_i, d_i))
        iv_i = ctext

    return ''.join(list(dict.fromkeys(decrypted_text)))
Ejemplo n.º 8
0
def main():
    with open('20.txt', 'r') as f:

        plaintext = f.readlines()
        encrypt_lines(plaintext)
        #print(ciphertexts)
        block_len = len(min(ciphertexts, key=len))
        blocks = [ctext[:block_len] for ctext in ciphertexts]

        potential_keys = []
        transposed_blocks = transpose_blocks(bytes.fromhex(''.join(blocks)),
                                             int(block_len / 2))

        #print(f"\n------\nUsing KEYSIZE = {key_sz}\n------")
        probable_key = ''
        for block in transposed_blocks:
            block_hex = bytes([ord(c) for c in block]).hex()
            #print(block, block_hex)
            #print( xor_single_byte(block.encode()) )
            (decrypted_str, score, key_byte) = xor_single_byte(block_hex)
            if score != 0:
                probable_key += chr(key_byte)

        if block_len / 2 == len(probable_key):
            potential_keys.append(probable_key)

        print(f"\nProbable key is \"{potential_keys}\"\n\n")

        # TODO: currently only decrypts the first <shortest-length-ciphertext> chars of every line since that's what challenge says
        # the rest of the string could be decrypted by simply finding the next shortest string and
        # continuing based off that length, but the concept here should already be clear enough.
        probable_key = bytes([ord(c) for c in probable_key]).hex()
        dec_message = [
            bytes.fromhex(xor_hex_strings(probable_key, block)).decode()
            for block in blocks
        ]

        for i in range(len(dec_message)):
            assert dec_message[i].encode().hex() == base64.b64decode(
                plaintext[i])[:53].hex()