This is an old revision of the document!
In this lab we'll do some exercises with Message Authentication Codes.
In this exercise we will attack an insecure MAC algorithm by showing that an adversary can forge a (message, tag) pair without first querying a $\mathsf{Tag}$ oracle with the message.
Let $F$ be a $\mathsf{PRF}$. Show that the following MAC is insecure by constructing an efficient adversary with non-negligible advantage. The key is $k \in \{0, 1\}^n$, and for any message $m = m1 \| m2$ with $\left|m_1\right| = \left|m_2\right| = n$, the MAC is computed as:
$\mathsf{Tag}(k, m_1 \| m_2) = F_k(m_1) \| F_k(F_k(m_2)) $
In this exercise you will perform a Birthday attack on SHA256.
Your goal is to find two messages, $M_1$ and $M_2$, such that for the first four bytes $\mathsf{SHA256}(M_1) = \mathsf{SHA256}(M_2)$.
The collision will be $32$ bits long, which means you will need $2^{16}$ random messages in your attack. Note that the attack is not guaranteed to succeed; on average, two iterations of the attack are required to find a collision.
import sys import string import base64 from Crypto.Hash import SHA256 def raw2hex(raw): return raw.encode('hex') def hex2raw(hexstring): return base64.b16decode(hexstring) hexdigits = '0123456789ABCDEF' def hash(message): h = SHA256.new() h.update(message) return h.digest() def main(): # Try to find a collision on the first 4 bytes (32 bits) # Step 1. Generate 2^16 different random messages # Step 2. Compute hashes # Step 3. Check if there exist two hashes that match in the first # four bytes. # Step 3a. If a match is found, print the messages and hashes # Step 3b. If no match is found, repeat the attack with a new set # of random messages pass if __name__ == "__main__": main()