예제 #1
0
def edit_ctr(ciphertext: bytes, key: bytes, offset: int, newtext: bytes) -> bytes:
    """
    Given the input `ciphertext`, decrypts using the `key`, seeks into the
    text to the `offset`, and overwrites `newtext` in. If `offset` is greater
    than the length of the original ciphertext, throws a ValueError.
    """
    if offset > len(ciphertext):
        raise ValueError('Offset must be less than or equal to the length of the ciphertext')

    plaintext = aes_ctr(key, NONCE, ciphertext)

    modified_plaintext = plaintext[:offset] + newtext + plaintext[offset + len(newtext):]
    return aes_ctr(key, NONCE, modified_plaintext)
예제 #2
0
def encrypt(msg: bytes) -> bytes:
    """ Sandwiches user input between two existing strings, surrounding any ';'
    or '=' characters in single quotes. Pads and encrypts in AES CTR and returns
    the encrypted messge.
    """
    # I interpreted "quote out" to mean surround disallowed characters with
    # single quotes
    msg_str = msg.decode()
    msg = CLEAN_RE.sub(r"'\1'", msg_str)

    # Convert string (necessary for regex replacement) back to bytes
    msg = bytes(msg.encode())

    # Tack on the prefix and suffix
    msg = PREFIX + msg + SUFFIX
    return aes_ctr(KEY, NONCE, msg)
예제 #3
0
#!/usr/bin/env python

from base64 import b64decode
from os import urandom

from cryptopals_10 import xor
from cryptopals_18 import aes_ctr
from cryptopals_19 import guess_aes_ctr_keystream

if __name__ == '__main__':
    print('Challenge #20 - Break fixed-nonce CTR statistically')

    nonce = 0
    key = urandom(16)

    ciphertexts = []
    with open('data/20.txt', 'rb') as f:
        for line in f:
            ciphertexts.append(aes_ctr(key, nonce, b64decode(line)))

    guessed_keystream = guess_aes_ctr_keystream(ciphertexts)
    print(guessed_keystream)
    for ct in ciphertexts:
        print(xor(guessed_keystream, ct))
예제 #4
0
def is_admin(ciphertext: bytes) -> bytes:
    """ Returns whether or not an admin key-value pair is present in the
    decrypted string.
    """
    msg = aes_ctr(KEY, NONCE, ciphertext)
    return b';admin=true;' in msg
예제 #5
0
        best_score = None
        best_byte = None
        for test_byte in range(0, 256):
            test_score = score_english(bytes([i ^ test_byte for i in current_bytes]))
            if best_score is None or test_score > best_score:
                best_score = test_score
                best_byte = test_byte

        guessed_keystream.append(best_byte)

        idx += 1

    return guessed_keystream


if __name__ == '__main__':
    print('Challenge #19 - Break fixed-nonce CTR mode using substitutions')

    nonce = 0
    key = urandom(16)

    ciphertexts = set()
    for plaintext in INPUTS:
        ciphertexts.add(aes_ctr(key, nonce, plaintext))

    guessed_keystream = guess_aes_ctr_keystream(ciphertexts)

    print(f'Guessed Keystream: {bytes(guessed_keystream)}')
    for ct in ciphertexts:
        print(xor(guessed_keystream, ct))
예제 #6
0
    Given the input `ciphertext`, decrypts using the `key`, seeks into the
    text to the `offset`, and overwrites `newtext` in. If `offset` is greater
    than the length of the original ciphertext, throws a ValueError.
    """
    if offset > len(ciphertext):
        raise ValueError('Offset must be less than or equal to the length of the ciphertext')

    plaintext = aes_ctr(key, NONCE, ciphertext)

    modified_plaintext = plaintext[:offset] + newtext + plaintext[offset + len(newtext):]
    return aes_ctr(key, NONCE, modified_plaintext)


def ecb_decrypt(key, file_path):
    with open(file_path, 'rb') as f:
        text = base64.b64decode(f.read())

        cipher = AES.new(key, AES.MODE_ECB)  # IV is ignored
        return cipher.decrypt(text)


if __name__ == '__main__':
    print('Challenge #25 - Break "random access read/write" AES CTR')

    key = os.urandom(16)
    unknown_plaintext = ecb_decrypt(b'YELLOW SUBMARINE', 'data/25.txt')
    ciphertext = aes_ctr(key, NONCE, unknown_plaintext)

    plaintext = edit_ctr(ciphertext, key, 0, ciphertext)
    assert unknown_plaintext == plaintext