Exemple #1
0
def padding_oracle_attack(cipher: bytes, bs: int = 16) -> bytes:
    size = len(cipher)
    if size < bs * 2:
        raise Exception("Can only attack more than 2 block sizes")
    res = reduce(list.__add__,
                 [crack_block(cipher[index - (2 * bs):index])
                  for index in range(bs * 2, size + 1, bs)])
    return strip_padding(bytes(res), False)
Exemple #2
0
    def test_padding(self):
        if "padding" not in self.tests:
            self.skipTest("")

        test = b"1" + b"\x0f" * 15
        actual = strip_padding(test)
        expected = b"1"
        self.assertEqual(expected, actual)

        test = b"21" + b"\x0f" * 14
        self.assertRaises(WrongPaddingException, strip_padding, test)

        test = b"\x10" * 15 + b"\0"
        self.assertRaises(WrongPaddingException, strip_padding, test)

        test = b"\x10" * 16
        actual = strip_padding(test)
        expected = b""
        self.assertEqual(expected, actual)
Exemple #3
0
def crack_ecb_simple(func: Callable[[bytes], bytes], left_base_size: int = 0) -> bytes:
    # block_size = find_block_size(func)  # wrong
    block_size = 16
    answer = []
    base_byte = b"A"
    base_offset = round_up(left_base_size, block_size)
    lefter = base_byte * (base_offset - left_base_size)

    if not ecb_or_cbc(func, base_offset):
        raise Exception("This is not a ECB oracle")

    guess_data_size = len(func(lefter))

    zip_vars = (
        (x // block_size,  # distance
         block_size - x % block_size - 1)  # padding_size
        for x in range(guess_data_size)
    )
    for distance, padding_size in zip_vars:
        # as left part is always 15 bytes, for the first round we need padding
        # and for all consecutive blocks we don't, so:
        # bool(distance) ^ 1 returns 0 if (distance > 0)
        left_padding_size = padding_size * (bool(distance) ^ 1)

        left_data_size = block_size - left_padding_size - 1
        left = (base_byte * left_padding_size) + bytes(answer[-left_data_size:])
        right = (base_byte * padding_size)
        blocks = [left + bytes([b]) + right for b in range(256)]
        block_pairs = [(block, func(lefter + block)) for block in blocks]
        for block, enc_block in block_pairs:
            enc_offset = base_offset + block_size * (distance + 1)

            left_start = base_offset
            right_start = enc_offset

            if enc_block[left_start:left_start + block_size] == enc_block[right_start:right_start + block_size]:
                x = block[block_size - 1]
                answer.append(x)
                break
    if len(answer) % block_size > 0:
        return bytes(answer)
    else:
        return strip_padding(bytes(answer))
Exemple #4
0
    def test_cbc(self):
        if "cbc" not in self.tests:
            self.skipTest("")
        data = b"1234567890"
        key = b"YELLOW SUBMARINE"
        iv = 16 * b"\0"

        cipher = AES.new(key, AES.MODE_CBC, iv)
        expected = cipher.encrypt(pkcs7_pad(data, AES.block_size))
        actual = encrypt_cbc(data, key, iv)
        self.assertEqual(expected, actual)

        cipher = AES.new(key, AES.MODE_CBC, iv)
        expected = strip_padding(cipher.decrypt(expected))
        actual = decrypt_cbc(actual, key, iv)
        self.assertEqual(expected, actual)

        data = b"1234567890abcdef"
        cipher = AES.new(key, AES.MODE_CBC, iv)
        expected = cipher.encrypt(data)
        actual = encrypt_cbc(data, key, iv)
        self.assertEqual(expected, actual)
Exemple #5
0
def decrypt_profile(data: bytes) -> dict:
    global key
    ret = decrypt_aes_128_ecb(data, key)
    ret = strip_padding(ret)
    ret = kv_parse(ret.decode("ascii"))
    return dict(ret)