Esempio n. 1
0
def challenge_6():
    with open('6.txt') as f:
        data = base64.b64decode(f.read())
    keysize_candidates = list()
    for keysize in range(1, 30):
        chunks = chunk_into(data, keysize)
        pairs = itertools.combinations(chunks[:4], 2)
        score = 0
        for a, b in pairs:
            hscore = hamming(a, b)
            logger.debug(hscore)
            score += hscore / keysize
        score /= 4
        keysize_candidates.append((keysize, score))
    keysize_probability = sorted(keysize_candidates, key=lambda x: x[1])
    logger.info("Probable keysizes: {}".format(keysize_probability[:5]))
    for keysize, score in keysize_probability[:3]:
        key_ints = list()
        logger.debug(keysize)
        chunks = chunk_into(data, keysize)
        transposed = zip(*chunks[:-1])
        for c in transposed:
            try:
                _, key_int = english_freq(bytes(c))
                key_ints.append(key_int)
            except TypeError:
                break

        if len(key_ints) == keysize:
            return xor_with_key(data, bytes(key_ints))
Esempio n. 2
0
def challenge_6():
    with open('6.txt') as f:
        data = base64.b64decode(f.read())
    keysize_candidates = list()
    for keysize in range(1, 30):
        chunks = chunk_into(data, keysize)
        pairs = itertools.combinations(chunks[:4], 2)
        score = 0
        for a, b in pairs:
            hscore = hamming(a, b)
            logger.debug(hscore)
            score += hscore / keysize
        score /= 4
        keysize_candidates.append((keysize, score))
    keysize_probability = sorted(keysize_candidates, key=lambda x: x[1])
    logger.info("Probable keysizes: {}".format(keysize_probability[:5]))
    for keysize, score in keysize_probability[:3]:
        key_ints = list()
        logger.debug(keysize)
        chunks = chunk_into(data, keysize)
        transposed = zip(*chunks[:-1])
        for c in transposed:
            try:
                _, key_int = english_freq(bytes(c))
                key_ints.append(key_int)
            except TypeError:
                break

        if len(key_ints) == keysize:
            return xor_with_key(data, bytes(key_ints))
Esempio n. 3
0
def challenge_14():
    oracle = C14Oracle()
    minimal_ct = oracle(b'')
    min_len = len(minimal_ct)
    logger.info("CT with empty payload {}: {}".format(min_len, minimal_ct))
    pushout = hdr = None
    prefix_pad_to_block_boundary = 0
    for i in range(1, BLOCKSIZE + 1):
        pairs = zip(chunk_into(oracle(i * b'x'), BLOCKSIZE),
                    chunk_into(oracle(i * b'y'), BLOCKSIZE))
        chunk_equality = [a == b for a, b in pairs]
        if hdr is None:
            hdr = chunk_equality.index(False) + 1
        falses = chunk_equality.count(False)
        logger.debug('i: {}, {}'.format(i, falses))
        logger.debug(chunk_equality)
        if not prefix_pad_to_block_boundary and falses > 1:
            prefix_pad_to_block_boundary = i - 1
        if pushout is None and len(chunk_equality) > min_len / BLOCKSIZE:
            pushout = i + 1
    prefix_len = hdr * BLOCKSIZE - prefix_pad_to_block_boundary
    plaintext_len = min_len - prefix_len - pushout + 1
    discard = hdr * BLOCKSIZE
    logger.info('Prefix len: {}'.format(prefix_len))
    logger.info('Plaintext len: {}'.format(plaintext_len))
    logger.info('Prefix pad to block boundary: {}'.format(
        prefix_pad_to_block_boundary))
    logger.info('Discard: {}'.format(discard))
    known = list()
    logger.info('Push out: {}'.format(pushout))
    goldindex = min_len
    while len(known) < plaintext_len:
        insert = (len(known) + pushout) * b'x'
        ct = oracle(insert)
        gold = ct[goldindex:]
        for c in string.printable:
            char = bytes((ord(c), ))
            filler = prefix_pad_to_block_boundary * b'x'
            plaintext = pkcs7pad(char + b''.join(known), BLOCKSIZE)
            compare_to = oracle(filler + plaintext)[discard:]
            # assert len(compare_to) == len(gold)
            # logger.info(compare_to)
            if compare_to.startswith(gold):
                known.insert(0, char)
                break
            logger.debug(known)

    return b''.join(known)
Esempio n. 4
0
def main():
    ct = encrypt()
    iv, *blocks = chunk_into(ct, BLOCKSIZE)
    logger.info(iv)
    logger.info(blocks)
    ret = list()
    prev_block = iv
    for block in blocks:
        known = list()
        while len(known) < BLOCKSIZE:
            i = len(known)
            known_trailer = bytes((ord(x) ^ y ^ (i + 1))
                                  for x, y in (zip(known, prev_block[-i:])))
            logger.debug("Trailer: {}".format(known_trailer))
            for c in range(256):
                char = bytes((c, ))
                fake_block = b'\x00' * (BLOCKSIZE - len(known_trailer) -
                                        1) + char + known_trailer
                if padding_oracle(fake_block + block):
                    Ca = char[0]
                    padsize = len(known) + 1
                    known.insert(
                        0, bytes((Ca ^ prev_block[-padsize] ^ padsize, )))
                    logger.info('Decrypted: {}'.format(b''.join(known)))
                    break
        ret.extend(known)
        prev_block = block
    return unpad(b''.join(ret))
Esempio n. 5
0
def challenge_12():
    with open('12.txt') as f:
        suffix = b64decode(f.read())
    blocksize = detect_blocksize(suffix)
    x = 2 * blocksize * b'A'
    ciphertext = deterministic_oracle(x, suffix)
    chunks = chunk_into(ciphertext, blocksize)
    if len(chunks) > len(set(chunks)):
        logger.info("Cipher is running in ECB mode")
    datalen = len(deterministic_oracle(b'', suffix))
    logger.critical(datalen)
    known = list()
    for offset in range(1, datalen):
        padder = (datalen - offset) * b'A'
        rtable = dict()
        for c in range(256):
            char = bytes((c, ))
            plain = padder + b''.join(known) + char
            # logger.debug(plain)
            rtable[deterministic_oracle(plain, suffix)[:datalen]] = char
        ciphertext = deterministic_oracle(padder, suffix)
        try:
            known.append(rtable[ciphertext[:datalen]])
        except KeyError:
            return unpad(b''.join(known))
Esempio n. 6
0
def main():
    ct = encrypt()
    iv, *blocks = chunk_into(ct, BLOCKSIZE)
    logger.info(iv)
    logger.info(blocks)
    ret = list()
    prev_block = iv
    for block in blocks:
        known = list()
        while len(known) < BLOCKSIZE:
            i = len(known)
            known_trailer = bytes((ord(x) ^ y ^ (i + 1)) for x, y in (zip(known, prev_block[-i:])))
            logger.debug("Trailer: {}".format(known_trailer))
            for c in range(256):
                char = bytes((c,))
                fake_block = b'\x00' * (BLOCKSIZE - len(known_trailer) - 1) + char + known_trailer
                if padding_oracle(fake_block + block):
                    Ca = char[0]
                    padsize = len(known) + 1
                    known.insert(0, bytes((Ca ^ prev_block[-padsize] ^ padsize,)))
                    logger.info('Decrypted: {}'.format(b''.join(known)))
                    break
        ret.extend(known)
        prev_block = block
    return unpad(b''.join(ret))
Esempio n. 7
0
 def decrypt(self, data):
     assert len(data) % 16 == 0
     blocks = chunk_into(data, 16)
     plain = list()
     for block in blocks:
         plain.append(xor_with_key(ECB(self.key).decrypt(block), self._state))
         self._state = block
     return unpad(b''.join(plain))
Esempio n. 8
0
def detect_blocksize(suffix):
    for i in range(3, 65):
        plain = b'A' * 64
        cipher = deterministic_oracle(plain, suffix)
        chunks = chunk_into(cipher, i)
        if chunks[0] == chunks[1]:
            logger.info('Block size = {}'.format(i))
            return i
Esempio n. 9
0
def challenge_13():
    min_len = len(profile_for(''))
    for i in range(BLOCKSIZE):
        if len(profile_for('x' * i)) > min_len:
            break
    spacing = i
    chunks = chunk_into(
        profile_for(spacing * b'x' + pkcs7pad(b'admin', BLOCKSIZE)), BLOCKSIZE)
    cut = chunk_into(
        profile_for(spacing * b'x' + pkcs7pad(b'user', BLOCKSIZE)),
        BLOCKSIZE)[1]
    paste = chunks[1]
    for i in range(BLOCKSIZE):
        chunks = chunk_into(profile_for(i * b'x'), BLOCKSIZE)
        if chunks[-1] == cut:
            chunks[-1] = paste
            return parse_profile(b''.join(chunks)).items()
Esempio n. 10
0
 def encrypt(self, data):
     ret = list()
     blocks = chunk_into(data, BLOCKSIZE)
     for i, block in enumerate(blocks):
         _ks = self.cipher.encrypt(struct.pack('<2Q', self.nonce, i))
         logger.debug(block)
         logger.debug(_ks)
         ret.append(xor_with_key(block, _ks))
     return b''.join(ret)
Esempio n. 11
0
 def encrypt(self, data):
     ret = list()
     blocks = chunk_into(data, BLOCKSIZE)
     for i, block in enumerate(blocks):
         _ks = self.cipher.encrypt(struct.pack('<2Q', self.nonce, i))
         logger.debug(block)
         logger.debug(_ks)
         ret.append(xor_with_key(block, _ks))
     return b''.join(ret)
Esempio n. 12
0
 def decrypt(self, data):
     assert len(data) % 16 == 0
     blocks = chunk_into(data, 16)
     plain = list()
     for block in blocks:
         plain.append(
             xor_with_key(ECB(self.key).decrypt(block), self._state))
         self._state = block
     return unpad(b''.join(plain))
Esempio n. 13
0
 def encrypt(self, data):
     if not len(data) % 16 == 0:
         data = pkcs7pad(data, 16)
     blocks = chunk_into(data, 16)
     ciphertext = list()
     for block in blocks:
         cipherblock = ECB(self.key).encrypt(xor_with_key(block, self._state))
         ciphertext.append(cipherblock)
         self._state = cipherblock
     return b''.join(ciphertext)
Esempio n. 14
0
 def encrypt(self, data):
     if not len(data) % 16 == 0:
         data = pkcs7pad(data, 16)
     blocks = chunk_into(data, 16)
     ciphertext = list()
     for block in blocks:
         cipherblock = ECB(self.key).encrypt(
             xor_with_key(block, self._state))
         ciphertext.append(cipherblock)
         self._state = cipherblock
     return b''.join(ciphertext)
Esempio n. 15
0
def challenge_8():
    with open('8.txt') as f:
        candidates = (base64.b64decode(x) for x in f.readlines())
    best = None
    for candidate in candidates:
        chunks = chunk_into(candidate, 16)
        unique_chunks = len(set(chunks))
        if best is None:
            score = unique_chunks
            best = candidate
        elif unique_chunks < score:
            best = candidate
            score = unique_chunks
        logger.debug(unique_chunks)
    return best, score
Esempio n. 16
0
def challenge_8():
    with open('8.txt') as f:
        candidates = (base64.b64decode(x) for x in f.readlines())
    best = None
    for candidate in candidates:
        chunks = chunk_into(candidate, 16)
        unique_chunks = len(set(chunks))
        if best is None:
            score = unique_chunks
            best = candidate
        elif unique_chunks < score:
            best = candidate
            score = unique_chunks
        logger.debug(unique_chunks)
    return best, score
Esempio n. 17
0
 def test_chunking(self):
     self.assertEquals(chunk_into('foobarx', 3), ['foo', 'bar', 'x'])
Esempio n. 18
0
 def test_chunking(self):
     self.assertEquals(chunk_into('foobarx', 3), ['foo', 'bar', 'x'])
Esempio n. 19
0
def analyze(plain, chunk_count):
    analyzed = len(set(chunk_into(encryption_oracle(plain), BLOCKSIZE)))
    if chunk_count > analyzed:
        return 'ECB'
    else:
        return 'CBC'