コード例 #1
0
    def test_challenge26(self):
        key = crypto.encryption_key()
        nonce = '\x00' * 8
        ciphertext = encrypt_kvps('admin=true', key, nonce)
        self.assertFalse(is_admin(ciphertext, key, nonce),
                         'Should have escaped the =')

        # 0               1               2               3               4
        # comment1=cooking%20MCs;userdata=true;comment2=%20like%20a%20pound%20of%20bacon
        # comment1=cooking%20MCs;us;admin=true;comment2=%20like%20a%20pound%20of%20bacon
        ciphertext = encrypt_kvps('true', key, nonce)
        self.assertFalse(is_admin(ciphertext, key, nonce))

        # ciphertext ^ orig plaintext = keystream
        # keystream ^ (desired plaintext) = new ciphertext to splice in
        start = 25
        orig_plaintext = 'erdata'
        keystream = bitops.xor(ciphertext[start:start + len(orig_plaintext)],
                               orig_plaintext)

        tampered_chunk = bitops.xor(keystream, ';admin')

        tampered_ciphertext = (ciphertext[:start] + tampered_chunk +
                               ciphertext[start + len(tampered_chunk):])

        self.assertTrue(is_admin(tampered_ciphertext, key, nonce))
コード例 #2
0
def hmac(key, message):
    padding_length = sha1.Sha1Hash.block_size - len(key)
    if padding_length > 0:
        key += '\x00' * padding_length
    else:
        key = sha1.Sha1Hash().update(key).digest()

    full_message = (
        xor(key, '\x5c' * len(key)) +
        sha1.Sha1Hash().update(xor(key, '\x36' * len(key))).digest() + message)

    return sha1.Sha1Hash().update(full_message).digest()
コード例 #3
0
 def set_plaintext_char(self, index, pos, plaintext_val):
     if plaintext_val is None:
         self.keystream[pos] = None
     else:
         self.keystream[pos] = xor(
             self.ciphertexts[index][pos],
             plaintext_val
         )
コード例 #4
0
    def test_challenge2(self):
        hex_input1 = '1c0111001f010100061a024b53535009181c'
        hex_input2 = '686974207468652062756c6c277320657965'

        xor_result = xor(hex_to_bytes(hex_input1), hex_to_bytes(hex_input2))
        self.assertEquals(
            '746865206b696420646f6e277420706c6179',
            bytes_to_hex(xor_result)
        )
コード例 #5
0
    def test_challenge20(self):
        plaintexts = [
            base64_to_bytes(line)
            for line in utils.readlines('20.txt')
        ]

        key = encryption_key()
        nonce = '\0' * 8
        ciphertexts = [
            ctr_encrypt(m, key, nonce)
            for m in plaintexts
        ]

        # Because of the fixed-nonce, the encrypted keystream bytes are
        # repeated for every plaintext message.
        #
        # ciphertext[i] ^ keystream[i] = plaintext[i]
        #
        # We can create a transposed ciphertext message by concatenating
        # ciphertext[i] from every encrypted message and then xor'ing that
        # against a guessed keystream byte. Then we can test whether the
        # resulting plaintext looks like english based on character
        # distributions. If so, then we've figured out the keystream byte.

        keystream = ''
        for index in itertools.count():
            transposed = ''.join(m[index:index+1] for m in ciphertexts)
            if not transposed:
                break

            allowed_chars = None
            if index == 0:
                allowed_chars = string.ascii_uppercase + '"\''

            score, _, key = crack.find_best_single_byte_key(
                transposed,
                allowed_chars=allowed_chars
            )
            # print 'Best score for index {}: {}'.format(index, score)
            keystream += key[0]

        recovered_plaintexts = [
            bitops.xor(m, keystream) for m in ciphertexts
        ]

        # for m in recovered_plaintexts:
        #     print m

        self.assertIn(
            '\'Cause my girl is definitely mad / \'Cause it took us too long to do this album',
            recovered_plaintexts
        )
コード例 #6
0
def cbc_decrypt(ciphertext, key, iv):
    backend = default_backend()
    cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
    decryptor = cipher.decryptor()

    plaintext = ''
    block_size = len(iv)
    for start in range(0, len(ciphertext), block_size):
        end = start + block_size
        ciphertext_block = ciphertext[start:end]
        plaintext += xor(iv, decryptor.update(ciphertext_block))
        iv = ciphertext_block

    return strip_pkcs_7(plaintext)
コード例 #7
0
def find_best_single_byte_key(rawbytes, freq_vector=None, allowed_chars=None):
    best_key = None
    best_translation = None
    best_score = -1.0
    for key in single_byte_keys(len(rawbytes)):
        translation = xor(rawbytes, key)
        score = english_score(translation,
                              freq_vector=freq_vector,
                              allowed_chars=allowed_chars)
        if score > best_score:
            best_score = score
            best_key = key
            best_translation = translation

    return (best_score, best_translation, best_key)
コード例 #8
0
def cbc_encrypt(plaintext, key, iv):
    backend = default_backend()
    cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
    encryptor = cipher.encryptor()

    padded = pkcs_7(plaintext, len(iv))
    ciphertext = ''
    for start in range(0, len(padded), len(iv)):
        end = start + len(iv)
        scrambled = xor(iv, padded[start:end])
        ciphertext_block = encryptor.update(scrambled)
        ciphertext += ciphertext_block
        iv = ciphertext_block

    return ciphertext
コード例 #9
0
    def test_challenge25(self):
        ciphertext = convert.base64_to_bytes(utils.read('25.txt'))
        plaintext = crypto.ecb_decrypt(ciphertext, 'YELLOW SUBMARINE')

        key = crypto.encryption_key()
        nonce = '\x00' * 8
        ciphertext = crypto.ctr_encrypt(plaintext, key, nonce)

        # The edit function lets us recover the original keystream because
        # in CTR mode: plaintext ^ keystream = ciphertext and then through
        # the magic of xor:
        #
        # plaintext ^ ciphertext = keystream
        #
        # Through the edit function, we know the plaintext and ciphertext
        # for every index in the byte stream.

        keystream = ''
        for offset in range(len(ciphertext)):
            new_ciphertext = edit(ciphertext, key, nonce, offset, 'A')
            keystream += bitops.xor(new_ciphertext[offset], 'A')

        recovered_plaintext = bitops.xor(ciphertext, keystream)
        self.assertEquals(plaintext, recovered_plaintext)
コード例 #10
0
    def test_challenge27(self):
        key = crypto.encryption_key()
        ciphertext = encrypt_kvps_cbc('hello', key)

        tampered = (ciphertext[:16] + ('\x00' * 16) + ciphertext[:16] +
                    ciphertext[16:])

        try:
            is_admin_cbc(tampered, key)
        except ValueError as e:
            expected_prefix = 'Invalid message '
            plaintext = e.message[len(expected_prefix):]

        # C1 = 0
        # P2 = D(E(P0 ^ IV)) ^ C1
        # P2 = P0 ^ IV ^ 0
        # P2 = P0 ^ IV
        # The first block in the recovered plaintext is P0 and iv = key so:
        # P0 ^ P2 = IV = KEY
        #
        # The 3rd plaintext block is
        # D(E(P0 ^ IV)) ^ 0
        recovered_key = bitops.xor(plaintext[:16], plaintext[32:48])
        self.assertEqual(key, recovered_key)
コード例 #11
0
 def test_xor_trim_to_shortest(self):
     self.assertEqual('\x00', bitops.xor('\x01', '\x01\x02'))
コード例 #12
0
 def _decrypt_char(self, index, ciphertext_val):
     if self.keystream[index] is None:
         return None
     else:
         return xor(self.keystream[index], ciphertext_val)
コード例 #13
0
def twister_convert(text, key):
    r = myrandom.MT19937(key & 0xffff)
    keystream = (chr(r.next() & 0xff) for _ in itertools.count())

    return ''.join(xor(a, b) for a, b in zip(text, keystream))
コード例 #14
0
def ctr_convert(text, key, nonce):
    blocks = (text[s:(s + 16)] for s in range(0, len(text), 16))

    return ''.join(
        xor(a, b) for a, b in zip(blocks, _ctr_keystream(key, nonce)))