Пример #1
0
def bytes_to_base64_original(data):
    b64 = ''
    for triplet in groups(data, 3):

        # 6 bits from triplet[0]
        r0 = triplet[0] >> 2

        if len(triplet) == 3:
            r1 = triplet[0] & 0b11
            r1 = r1 << 4
            temp = triplet[1] >> 4
            r1 = r1 | temp

            # 4 bits from triplet[1] and 2 bits from triplet[2]
            r2 = triplet[1] & 0b00001111
            r2 = r2 << 2
            temp = triplet[2] & 0b11000000
            temp = temp >> 6
            r2 |= temp

            # 6 bits from triplet[2]
            r3 = triplet[2] & 0b00111111

        elif len(triplet) == 2:

            # 2 bits from triplet[0] and 4 bits from triplet[1]
            r1 = triplet[0] & 0b11
            r1 = r1 << 4
            temp = triplet[1] >> 4
            r1 = r1 | temp

            # 4 bits from triplet[1] and 2 bits from triplet[2]
            r2 = triplet[1] & 0b00001111
            r2 = r2 << 2

            # triplet[2] is empty
            r3 = 64

        elif len(triplet) == 1:
            print('triplet is length 1')
            print('before join', triplet)
            triplet = b''.join((triplet, b'\x00'))
            print('after join', triplet)

            # 2 bits from triplet[0] and 4 bits from triplet[1]
            r1 = triplet[0] & 0b11
            r1 = r1 << 4
            temp = triplet[1] >> 4
            r1 = r1 | temp

            r2 = 64
            r3 = 64

        b64 += base64_table[r0]
        b64 += base64_table[r1]
        b64 += base64_table[r2]
        b64 += base64_table[r3]

    return b64
Пример #2
0
def detect_aes_ecb(data):
    '''
    Detects AES ECB by looking for two identical blocks.
    :param data: Encrypted bytes.
    :return: Bool, true if CBC is detected.
    '''
    for combo in itertools.combinations(util.groups(data[:-1], BLOCK_SIZE), 2):
        if combo[0] == combo[1]:
            return True
    return False
Пример #3
0
def base64_to_bytes(b64data):
    '''
    Decode Base64 bytestring to bytestring.
    One base64 digit is six bits of data.
    :param b64data:
    :return:
    '''

    if isinstance(b64data, str):
        b64data = b64data.encode()

    assert isinstance(b64data, bytes)

    decoded = bytearray()

    # b64data = b64data.replace(b'\n', b'')

    for quad in groups(b64data, 4):
        # print(quad, 'len(quad)', len(quad))

        # 6 high bits (00111111), 2 low bits (00110000)
        triplet_1 = (base64_table.index(chr(quad[0])) << 2) + (
            base64_table.index(chr(quad[1])) >> 4)
        decoded.append(triplet_1)
        # print('triplet_1:', triplet_1)

        if quad[2] == ord('='):
            # print('quad[2] is =')
            # 4 high bits (00001111), 0 low bits (00000000)
            triplet_2 = ((base64_table.index(chr(quad[1])) & 0b00001111) << 4)
        else:
            # 4 high bits (00001111), 4 low bits (00111100)
            triplet_2 = ((base64_table.index(chr(quad[1])) & 0b00001111) <<
                         4) + (base64_table.index(chr(quad[2])) >> 2)
        if triplet_2 != 0:
            decoded.append(triplet_2)
        # print('triplet_2:', triplet_2)

        # 2 high bits (00000011), 6 low bits (00111111)
        if quad[3] == ord('='):
            # print('quad[3] is =')
            # triplet_3 = None
            pass
        else:
            triplet_3 = ((base64_table.index(chr(quad[2])) & 0b00000011) <<
                         6) + base64_table.index(chr(quad[3]))
            decoded.append(triplet_3)
            # print('triplet_3:', triplet_3)

        # print(triplet_1, triplet_2, triplet_3)
        # print(chr(triplet_1), chr(triplet_2), chr(triplet_3))

        # print('decoded:', decoded)

    return bytes(decoded)
Пример #4
0
def bytes_to_base64(data):
    '''

    :param data: Bytestring
    :return:
    '''
    # print('input', data)

    b64 = ''
    for triplet in groups(data, 3):
        len_triplet = len(triplet)  # Store in case len(triplet) == 1.
        # 6 bits from triplet[0]
        r0 = triplet[0] >> 2

        if len_triplet == 1:
            # Add a byte with zeros so that triplet[1] succeeds.
            # This changes the len(triplet), which is why we stored it earlier.
            triplet = b''.join((triplet, b'\x00'))
            r2 = 64
            r3 = 64

        # 2 bits from triplet[0] and 4 bits from triplet[1].
        r1 = triplet[0] & 0b11
        r1 = r1 << 4
        temp = triplet[1] >> 4
        r1 = r1 | temp

        if len_triplet > 1:

            # 4 bits from triplet[1] and 2 bits from triplet[2].
            r2 = triplet[1] & 0b00001111
            r2 = r2 << 2

            if len_triplet == 3:

                temp = triplet[2] & 0b11000000
                temp = temp >> 6
                r2 |= temp

                # 6 bits from triplet[2]
                r3 = triplet[2] & 0b00111111

            elif len_triplet == 2:

                # triplet[2] is empty
                r3 = 64

        b64 += base64_table[r0]
        b64 += base64_table[r1]
        b64 += base64_table[r2]
        b64 += base64_table[r3]

    # print('output', b64)
    return b64
Пример #5
0
def test_detect_aes_ecb():
    # Set 1, Challenge 8
    # 16 byte blocks
    with open("8.txt") as f:
        lines = f.readlines()
        for index, line in enumerate(lines):
            for combo in itertools.combinations(
                    util.groups(util.hexbytes_to_bytestr(line[:-1]), 16), 2):
                if combo[0] == combo[1]:
                    print(index, line)
        print(lines)
    assert detect_aes_ecb(lines[132])
Пример #6
0
def aes_cbc_decrypt(data, key, IV):
    '''
    Decrypt Cipher Block Chaining (CBC) with AES on each block.
    https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_(CBC)
    :param data: Encrypted bytes.
    :param key: Bytes to decrypt.
    :param IV: Initialization Vector. Must be block size (16 bytes default).
    :return:
    '''

    if len(IV) is not BLOCK_SIZE:
        raise ValueError("IV must be " + str(BLOCK_SIZE) + " bytes.")

    # AES instance for decrypting
    aes_cipher = AES.new(key=key, mode=AES.MODE_ECB)

    # iterator for grabbing sequential blocks from data
    next_block = util.groups(data, BLOCK_SIZE)
    all_blocks = list(next_block)

    # 0th block with IV
    cipher_block = all_blocks[0]

    # decrypt first block
    decrypt_block = aes_cipher.decrypt(cipher_block)

    # xor with IV
    xor_block = xor.fixed_xor(decrypt_block, IV)
    # print(xor_block, len(xor_block), type(xor_block))
    result = xor_block

    prev_cipher_block = cipher_block
    # while more data:
    for cipher_block in all_blocks[1:]:
        decrypt_block = aes_cipher.decrypt(cipher_block)
        xor_block = xor.fixed_xor(prev_cipher_block, decrypt_block)
        # print(xor_block, len(xor_block))
        result += xor_block
        prev_cipher_block = cipher_block
        # decrypt next block

    # detect and remove PKCS7 padding
    if result[-1] < BLOCK_SIZE:
        # how many bytes to remove? BLOCK_SIZE - result[-1]
        result = result[:-result[-1]]

    return result
Пример #7
0
def aes_cbc_encrypt(data, key, IV):
    '''
    Encrypt Cipher Block Chaining (CBC) with AES on each block.
    https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_(CBC)
    :param data: Plaintext bytes.
    :param key: Bytes to encrypt.
    :param IV: Initialization Vector. Must be block size (16 bytes default).
    :return:
    '''

    if len(IV) is not BLOCK_SIZE:
        raise ValueError("IV must be " + str(BLOCK_SIZE) + " bytes.")

    # AES instance for decrypting
    aes_cipher = AES.new(key=key, mode=AES.MODE_ECB)

    # iterator for grabbing sequential blocks from data
    next_block = util.groups(data, BLOCK_SIZE)
    all_blocks = list(next_block)

    # first block
    plain_block = all_blocks[0]

    # xor with IV
    xor_block = xor.fixed_xor(plain_block, IV)
    # print(xor_block, len(xor_block), type(xor_block))

    # encrypt
    encrypt_block = aes_cipher.encrypt(xor_block)
    result = encrypt_block

    prev_cipher_block = encrypt_block
    # while more data:
    for plain_block in all_blocks[1:]:
        if len(plain_block) < BLOCK_SIZE:
            plain_block = pkcs7pad(plain_block, BLOCK_SIZE)
        xor_block = xor.fixed_xor(prev_cipher_block, plain_block)
        decrypt_block = aes_cipher.encrypt(xor_block)
        # print(xor_block, len(xor_block))
        result += decrypt_block
        prev_cipher_block = decrypt_block
        # encrypt next block
    return result
Пример #8
0
    def __init__(self):

        self.headers = util.headers
        self.base_url = util.groups()
        print('Start to get friends list and save it for ./friends folder')
Пример #9
0
def test_solve_chall6():
    '''
    1) Let KEYSIZE be the guessed length of the key; try values from 2 to (say) 40.

    2) Write a function to compute the edit distance/Hamming distance between two strings. The Hamming distance is just
    the number of differing bits. The distance between:
        this is a test
        and
        wokka wokka!!!
        is 37. Make sure your code agrees before you proceed.

    3) For each KEYSIZE, take the first KEYSIZE worth of bytes, and the second KEYSIZE worth of bytes, and find the edit
    distance between them. Normalize this result by dividing by KEYSIZE.

    4) The KEYSIZE with the smallest normalized edit distance is probably the key. You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4 KEYSIZE blocks instead of 2 and average the distances.

    5) Now that you probably know the KEYSIZE: break the ciphertext into blocks of KEYSIZE length.

    6) Now transpose the blocks: make a block that is the first byte of every block, and a block that is the second byte of every block, and so on.

    7) Solve each block as if it was single-character XOR. You already have code to do this.

    8) For each block, the single-byte XOR key that produces the best looking histogram is the repeating-key XOR key byte for that block. Put them together and you have the key.
    '''

    KEYSIZE_RANGE_MIN = 2  # Inclusive range of possible key sizes to search
    KEYSIZE_RANGE_MAX = 40
    NUMBER_OF_BLOCKS = 4  # TODO 2, 4 also suggested.

    with open('6.txt') as f:
        # cipher_b64 = b''.join([x.rstrip('\n').encode() for x in f.readlines()])
        cipher_b64_str = ''.join([x.rstrip('\n') for x in f.readlines()])
        cipher_b64 = cipher_b64_str.encode()
        # print(cipher)
        # print()

        # TODO is this really one big string????

        # Un-Base64 AFTER joining, not before
        # cipher = base_64.base64_to_bytes(cipher_b64) # TODO doesn't match base64 result
        cipher = base64.b64decode(cipher_b64_str)
        print()
        # print(cipher, len(cipher))
        # print(cipher2, len(cipher2))

        # for cipher in cipher:

        likely_xor_key_length = find_xor_key_length(cipher, KEYSIZE_RANGE_MIN,
                                                    KEYSIZE_RANGE_MAX,
                                                    NUMBER_OF_BLOCKS)
        print('likely_xor_key_length', likely_xor_key_length)

        transposed = [bytearray(b'') for i in range(likely_xor_key_length)]
        for block in util.groups(cipher, likely_xor_key_length):
            if len(block) < likely_xor_key_length:
                continue
            for position in range(likely_xor_key_length):
                transposed[position].append(block[position])
        # pprint(transposed)
        # print(len(transposed))

        xor_decoded = []
        for index, transposed_block in enumerate(transposed):
            # print('decoding block:', transposed_block)

            # look at the decode results and scores
            decoded = decode_all_single_byte_xor(transposed_block)

            xor_decoded.append(decoded[0])
            # print(index, 'decoding result:', xor_decoded[index])

        # pprint(xor_decoded)

        xor_decoded_bytes = [sp.bytestr for sp in xor_decoded]
        key = [sp.key() for sp in xor_decoded]
        print(bytes(key))

        # de-transpose
        result = bytearray()
        for byte in zip_longest(*xor_decoded_bytes):
            # print(byte, type(byte))
            for b in byte:
                if b:
                    # print(b)
                    result.append(b)
        # print(result, len(result))
        # print(bytes(result).decode(), len(result))

        # also, instead of detransposing, xor original text with the key
        print(repeating_key_xor(cipher, key))
Пример #10
0
def say(line: str) -> str:
    """
    Parameters:
        :param line: string of line that needs to be processed
    Return:
        str - text that was printed
    """
    # Exporting it to the transpiler where the while loop works
    global transpile, tabnum
    listed = list(line)
    out = ""
    start = None
    quotes = ["'", '"']
    quote_used = ""
    if len(util.groups(line, '"', "+")) > 1:
        groups = util.groups(line, '"', "+")
        out = ""
        tout = []
        for i in groups:
            i = i.strip(" ")
            if i.startswith("say"):
                i = i.replace("say ", "")
                if i.startswith('"'):
                    i = "".join(list(i)[1:])
                i = i.rstrip('"')
                if transpile:
                    if i in variables.keys():
                        tout.append([i, 0])
                    else:
                        tout.append([i, 1])
                    continue
                print(i, end="")
                out += str(i)
            elif i.startswith('"'):
                i = i.strip('"')
                if transpile:
                    tout.append([i, 1])
                    continue
                print(i, end="")

                out += str(i)
            else:
                try:
                    if transpile:
                        tout.append([i, 0])
                        continue
                    print(variables[i], end="")
                    out += str(variables[i])
                except KeyError:
                    raise Exception("Variable not found")
        if transpile:
            transpiler.add_line("    " * tabnum +
                                transpiler.fill_print_text_var(tout))
            return "__TRANSPILER.IGNORE.OUT__"
        print("")
        return out
    elif util.count("'", line) == 0 and util.count('"',
                                                   line) == 0 and "," in line:
        line = line.rstrip("\n")
        line = line.lstrip("say")
        line = line.replace(" ", "")
        line = line.split(",")
        full_out = ""
        for i in line:
            try:
                print(variables[i], end=" ")
                full_out += str(variables[i]) + " "
            except KeyError:
                raise Exception("Variable not found")
        print("\n", end="")
        full_out += "\n"
        return full_out

    elif util.count("'", line) == 0 and util.count('"', line) == 0:
        line = line.rstrip("\n")
        line = line.lstrip("say")
        line = line.lstrip(" ")
        try:
            if not transpile:
                print(variables[line])
            else:
                transpiler.add_line("    " * tabnum +
                                    transpiler.fill_print_plain_var(line))
        except KeyError:
            raise Exception("Variable not found")
        return variables[line]

    else:
        to_say = list(re.findall(r"say[ ]*?['\"](.+)['\"]", line))
        if len(to_say) > 0:
            if transpile:
                transpiler.add_line("    " * tabnum +
                                    transpiler.fill_print_plain(to_say[0]))
            else:
                print(to_say[0])
        else:
            raise Exception(
                f"Error on line: {line}\nInvalid syntax for say statement. Did you add too many spaces or forget quotes?"
            )

        return to_say[0]