This is an old revision of the document!
In this lab we'll do some exercises with Message Authentication Codes.
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()
In this exercise you will perform a timing attack against HMAC.
You are given access to an HMAC $\mathsf{Verify}$ oracle, which tests whether the received HMAC matches the one computed using the secret key. Timing attacks exploit naive equality comparisons between the received and computed HMACs (for example, the comparison is done byte by byte; more checks means more latency).
Your task is to produce a forged tag for the message 'Test' without knowing the key. Do this by iterating through all possible values for a specific byte; when the oracle's latency for a certain value seems larger than the rest, it suggests that the equality test returned True and the oracle passed to the next byte.
Try to start by finding the first byte and checking your result with the TA.
You can use time.clock()
before and after each oracle query to measure its runtime.
import sys import random import string import time import itertools import operator import base64 from Crypto.Hash.HMAC import HMAC def raw2hex(raw): return raw.encode('hex') def hex2raw(hexstring): return base64.b16decode(hexstring) def slow_foo(): p = 181 k = 2 while k < p: if p % k == 0: return k += 1 def verify(message, tag): k = '0123456789ABCDEF' # Use MD5 for HMAC digest = HMAC(k, message).digest() for i in range(16): # Artificially extend byte comparison duration slow_foo() if tag[i] != digest[i]: return False return True hexdigits = '0123456789ABCDEF' def main(): message = 'Test' # Step 1. Iterate through all possible first byte values, and call the # Verify oracle for each of them # Step 2. Store the byte which caused the longest computation time # Step 3. Continue the operation for each byte (except the last) # Step 4. Guess the last byte, and query the oracle with the complete tag mytag = '???' result = verify(message, mytag) if result == True: print mytag if __name__ == "__main__": main()