Beispiel #1
0
    def recieve(self, msg: bytes, iv: bytes) -> bytes:
        # Relay to B
        ciphertext, iv = self.echo.recieve(msg, iv)

        k = dh_digest(0)
        print('MITM:', pkcs7_strip(cbc_decrypt(ciphertext, k, iv)))

        return ciphertext, iv
Beispiel #2
0
    def recieve(self, msg: bytes, iv: bytes) -> bytes:
        """Recieves a message, decrypts it with A's key, and then re-encrypts
        with a new IV and returns

        Returns:
            (bytes, bytes): msg, iv tuple
        """
        s = modpow(self.A, self.b, self.p)
        k = dh_digest(s)
        plaintext = pkcs7_strip(cbc_decrypt(msg, k, iv))

        iv = os.urandom(16)
        return cbc_encrypt(plaintext, k, iv), iv
Beispiel #3
0
def has_valid_padding(ciphertext: bytes, iv: bytes) -> bool:
    """
    Decrypts the input ciphertext using the provided IV and returns a boolean
    representing whether or not it has valid padding.
    """
    msg = cbc_decrypt(ciphertext, KEY, iv)

    valid = True
    try:
        # Strip the padding; raises an exception if padding is invalid
        pkcs7_strip(msg)
    except ValueError:
        valid = False

    return valid
Beispiel #4
0
    g = 5

    A, a = dh_key(p, g)
    echo = Echo(p, g, A)

    # Test basic echo
    plaintext = b'some plaintext'

    key = dh_digest(modpow(echo.B, a, p))
    iv = os.urandom(16)
    ciphertext = cbc_encrypt(plaintext, key, iv)
    resp_ciphertext, resp_iv = echo.recieve(ciphertext, iv)

    # The sent and recieved plaintexts should be identical, after padding is
    # stripped away
    resp_plaintext = pkcs7_strip(cbc_decrypt(resp_ciphertext, key, resp_iv))
    assert plaintext == resp_plaintext

    # MITM
    mitm = Middleman(p, g, A)

    plaintext = b'top secret, do not read'
    key = dh_digest(modpow(mitm.B, a, p))
    iv = os.urandom(16)
    ciphertext = cbc_encrypt(plaintext, key, iv)
    resp_ciphertext, resp_iv = mitm.recieve(ciphertext, iv)

    # From A's perspective, responses should still be decryptable
    resp_plaintext = pkcs7_strip(cbc_decrypt(resp_ciphertext, key, resp_iv))
    assert plaintext == resp_plaintext
Beispiel #5
0
def is_admin(ciphertext: bytes) -> bytes:
    """ Returns whether or not an admin key-value pair is present in the
    decrypted string.
    """
    msg = cbc_decrypt(ciphertext, KEY, IV)
    return b';admin=true;' in msg
Beispiel #6
0
        # Generate a random key, and encrypt the (padded, from challenge #16) ciphertext
        key = iv = os.urandom(16)
        ciphertext = escaped_cbc_encrypt(plaintext, key, iv)

        # Compose a new ciphertext, composed of:
        # 1. First ciphertext block (unchanged)
        # 2. Completely zeroed block
        # 3. First ciphertext block
        ciphertext = list(ciphertext)
        ciphertext = ciphertext[0:16] + [0x00] * 16 + ciphertext[0:16]
        ciphertext = bytes(ciphertext)

        # Decrypt our ciphertext, then run it through the plaintext
        # verification function, which will raise an error indicating the ascii
        # isn't printable with the decrypted plaintext
        plaintext = cbc_decrypt(ciphertext, key, iv)
        try:
            verify_plaintext(plaintext)
        except Exception as e:
            # Search the output for the plaintext, and convert back to a format we can use (bytes)
            match = ERROR_RE.search(str(e))
            plaintext = str_to_bytes(match.group(1))

        # Now XOR the first and last decrypted blocks
        discovered_key = xor(plaintext[0:16], plaintext[32:48])

        assert key == discovered_key, f"Discovered key {discovered_key} doesn't match actual key {key}"

    print()