# Homework 6 (FCS)
## Exercise 1
```python=
# hw6 SHA
import os
import sys
import hashlib
import random
import timeit
import random
import binascii
import numpy as np
def ex1():
btxt1 = b'51.505-Foundations-of-Cybersecurity-MSSD'
btxt2 = b'51.505-Foundations-of-Cybersecurity-MSSd'
sha_btxt1 = hashlib.sha1(btxt1)
sha_btxt2 = hashlib.sha1(btxt2)
return sha_btxt1.hexdigest(), sha_btxt2.hexdigest()
```
<sha1 HASH object @ 0x000002653F669FB0>
<sha1 HASH object @ 0x000002653F79B210>
sha_btxt1.hexdigest() => `d2d2b25b4ee22957a08c41bfcb12e3b16e810699`
sha_btxt2.hexdigest() => `da7e687280aca8cd68a50ca5c1445f82da9783f7`
## Exercise 2
```python=
import os
import sys
import hashlib
import random
import timeit
import random
import binascii
import numpy as np
def ex2():
n = [8, 16]
mean_time = {n[0] : [], n[1] : []}
# n = 8 => hashed.append(...).hexdigest()[0:2]
# n = 16 => hashed.append(...).hexdigest()[0:4]
for x in range(30):
for k in n:
rd512 = [hex(random.getrandbits(512))]
collision_found = False
start = timeit.default_timer()
bites = int(k/4)
hashed = [hashlib.sha512(binascii.unhexlify(rd512[0][2:].zfill(128))).hexdigest()[0:bites]]
while not collision_found:
# generate a new random message
temp = hex(random.getrandbits(512))
rd512.append(temp)
hashed.append(hashlib.sha512(binascii.unhexlify(temp[2:].zfill(128))).hexdigest()[0:bites])
for i in range(0, len(rd512)): # sequentially pick each message/hash from the list
for j in range(i+1, len(rd512)): # and compare it with every other one
if hashed[i] == hashed[j]:
collision_found = True
end = timeit.default_timer()
print("\nMessage 1: ", rd512[i])
print("Corresponding Hash: ", hashed[i])
print("\nMessage 2: ", rd512[j])
print("Corresponding Hash: ", hashed[j])
time_taken = end - start
break
if collision_found:
break
print(f'For n = {k} A total of {len(rd512)} messages generated.')
print(f'For n = {k} A total of {len(hashed)} hashes computed.')
mean_time[k].append(time_taken)
for key, val in mean_time.items():
print(f'\nn = {key} on average takes {np.mean(val)} s')
```
Results:
```
Message 1: 0x59ac8f8e3fe67e93974f276fd88f97149d3f6fe3483b0246306bdf32571de9261731e150d365ab36a3929a05e5820d344468c24349ab09b490f8e304453d23c5
Corresponding Hash: 81
Message 2: 0x29f373b96e481c2707d91d15527e8dde55054009a4d207f2ab1f028cbf66beabcd5a9256f9058e8fc8138649fd2bfbc4c31118ea8216c083f16bdc8827fae0ae
Colliding Hash: 81
For n = 8 A total of 17 messages generated.
For n = 8 A total of 17 hashes computed.
Message 1: 0xd37693ac2c2c9cca567cf8f744be1f551d42359b5581e6b1cf52ddcde6fa51cc7456649dc5edb344cfd2c9991e0b1b78b2e0daaf980e78356f50c6d1db2a2410
Corresponding Hash: 0ca7
Message 2: 0x176aad7b3001d39e7e75ffa846a938f624186f28515c5c5f63055d0e9f667b5b3ce8fc22cbfb607d9a40263e3602c2cda8ea6a8d1f455d7f26704a504e16490d
Colliding Hash: 0ca7
For n = 16 A total of 250 messages generated.
For n = 16 A total of 250 hashes computed.
Message 1: 0x16c912771ba9acbd9552903eda53abf635584472191521b2ab85dcc5662dd2afc146d6cb16b696e2c1a0799ed0b6e7c2a68daeb9555432558f8afa9ea20d6d42
Corresponding Hash: 2a
Message 2: 0x73526f1bbd730438c7b8a07889a6d26f45a9a466e18c7469d48ca51fb87abe6bd5925e0b8fa0512741ae30f87c76aeb390444ea7831a1d6d4f83f4a6bd1c344b
Colliding Hash: 2a
For n = 8 A total of 16 messages generated.
For n = 8 A total of 16 hashes computed.
Message 1: 0x2defbf9a4297728d03efceedfbe6ca986fdfe042bbb2edba31557d47e1e9f6052b55425cb52b62509ddd9615b3ea4b49fb7261cbac5ea3235171353b9e54c1e7
Corresponding Hash: 116d
Message 2: 0x4e7622a81b772b58c2e1d075ec9b7437be672cde784ccd710e3d09c239d98fa1f4c4222f838e31902c433ec9fb62139821db156c6d6dff708ea1462fd67fb31
Colliding Hash: 116d
For n = 16 A total of 346 messages generated.
For n = 16 A total of 346 hashes computed.
Message 1: 0x9abec72a7de5363f76761c1a9c38ea703737d62ebe8e6512dcbb73e3b1c9258692611ccd9017e33e8131c6c845da2abe869a601cc3b001910a4fff52b646af3f
Corresponding Hash: dc
Message 2: 0xc29bc570014bb95f22fb03799f59cccf66a8e0d29d053a436b270fa22ca5bbec5588471538225fa93da50416172a521161fb14d41862c84d6dfdec8e63a1e71a
Colliding Hash: dc
For n = 8 A total of 17 messages generated.
For n = 8 A total of 17 hashes computed.
Message 1: 0x14b951d006bd2d3838839b68ebe675c131dd59c3f67a0552f769e33ea2c6fb31c098114778b16ec1a2ef5c0c496a63cf0a1bd76dcbc5c7301c63c7287c9321fa
Corresponding Hash: 9bc3
Message 2: 0x5fec090b49f34d6c945e4cf053b47df7d187b818c814586b26bf76841d662613db92b6542afe2f128e00edf165fdf1a885806189f37cd2b98760a68218312a4e
Colliding Hash: 9bc3
For n = 16 A total of 236 messages generated.
For n = 16 A total of 236 hashes computed.
Message 1: 0xf04fce383d0fe008fcf0d2c008bf992c890e4c1f013a3de9baa461031251b5c1c841d27766363f9af3d4667e9a405fb0e5e6ecee09af76d3b9cfb16d3090d434
Corresponding Hash: 1b
Message 2: 0x37d531773032d6a5f9c517d22cb7524a6254ac38392cc4ec8b3c74ba71020d5a10d4423107793bf44fc299cad348f2268cf79beb086141adfc7bbb888a0f8dc5
Colliding Hash: 1b
For n = 8 A total of 14 messages generated.
For n = 8 A total of 14 hashes computed.
Message 1: 0x13c02723ac2c882aa9933d70321a079be86074bcbe1d415ff2037f7fed2e0aa22382867e9a851e2dfaf18bf00365481785513e792e0cad71bc963514379e968b
Corresponding Hash: 7ccc
Message 2: 0xf313470f43b411ac68bba09d67717a95faa39a64215f2b1582f3d311fa4374c7d3d4178fca747e2b0307d3772a707711f3536d25911bebc3c4f990ac4cde3111
Colliding Hash: 7ccc
For n = 16 A total of 435 messages generated.
For n = 16 A total of 435 hashes computed.
Message 1: 0x6319d8ce028486d648bfc09fcf7f44a94174f4d74bf2a938d0223af30e60fad95554ec14f58bbb942d947359f04635ceead5dfccb0a5fa7b3b60ab5dde4be340
Corresponding Hash: 10
Message 2: 0xbaa9ed932e48973db7acb5314ecee2522689cd5ada2c5437102eda3c6efb9699b4854499a84535098260ce2c812a5e4290bbf8ce3d172f433d077ba83d7ff5c7
Colliding Hash: 10
For n = 8 A total of 14 messages generated.
For n = 8 A total of 14 hashes computed.
Message 1: 0xafa9dc40788ecb96114a230281a83fd8aa68c92268be832934f655159e47bf110f9d741d6f2f8383e2c9c60b8140b1a400e0f5f9789611c9573db7ecbd53108e
Corresponding Hash: c74f
Message 2: 0xdf72f9a87de1be4ee53de28145f95f78fc9703315d463fa354cc1f331679357e940744438eb4e92715368390c2bad30b342df9a0e510ead9b741309c01d3a463
Colliding Hash: c74f
For n = 16 A total of 41 messages generated.
For n = 16 A total of 41 hashes computed.
n = 8 on average takes 0.00015161999999998565 s
n = 16 on average takes 0.32491243999999997 s
n = 8 on average the number of messages are 15.6
n = 16 on average the number of messages are 261.6
```
The colliding hashes can be seen in the snippets of the results.
On average (for 30 iterations) H8 takes 0.00015161999999998565 s
On average (for 30 iterations) H16 takes 0.32491243999999997 s
## Exercise 3
```python=
def ex3():
ns = [8,16]
for n in ns:
counter = 0
preimage_found = False
start = timeit.default_timer()
bites = int(n/4)
while not preimage_found:
counter += 1
# generate a random message
rd512 = hex(random.getrandbits(512))
hashed = hashlib.sha512(binascii.unhexlify(rd512[2:].zfill(128))).hexdigest()[0:bites]
if hashed == "0"*bites:
preimage_found = True
end = timeit.default_timer()
break
print("Took", end - start, "seconds to find preimage.")
print("The preimage found is ", rd512, " after generating ", counter, "messages.")
print("The full SHA512 hash is ", hashlib.sha512(binascii.unhexlify(rd512[2:].zfill(128))).hexdigest())
```
Results
```
For H8 It took 0.00039320000000042654 seconds to find preimage.
The preimage found is 0x491b73a0d246dd6ab9336c26715fc36230a4aae62155f1d520fe2f917ff05b8535c2a1ce2c8c7dcd1b04a01c9ba80a9e53ac91e63ad1dbafc3b61c198995fce3 after generating 140 messages.
The full SHA512 hash is 000b14f3f660a7414ccf27befac3de7fc6b81d77cef09b89affc62a1621a778dd99dce163766e205be2b028ed01b0f4a301c228843b0ecd7f54a72adf4ea73b7
For H16 It took 0.15512569999999926 seconds to find preimage.
The preimage found is 0xe92a0859fcb5de01ff3c4327f1002be5503e689cad0d75a22d0ee763a11e1fda4a955b87be4d1875521be5091e01218724b2831f82aa218ae1140fd50d6a717f after generating 69533 messages.
The full SHA512 hash is 00006126ec80341585798d7c415d9520fd3e2990af3b6069355bc654da5641174234d5d8cc6a485133adc80637080ba6ae87ab676867a36a56834dde77b8e37a
```
## Exercise 4
```python=
def ex4():
# Generate Key
key = "1".zfill(32)
print("Key: ", key)
key = binascii.unhexlify(key)
# Generate Random Tag
_tag = hex(random.getrandbits(128))[2:].zfill(32)
print("Tag: ", _tag)
tag = binascii.unhexlify(_tag)
# Decrypt single blk to find tag.
cipher = AES.new(key, AES.MODE_CBC, IV = binascii.unhexlify('0'.zfill(32))) # use AES CBC
singleblk = int.from_bytes(cipher.decrypt(tag), byteorder='big')
# consider two-block message "blk1 || blk2", where we have a choice of blk2
blk2 = 1
'''
Assume as if tag was MAC(blk1 || blk2) = MAC((MAC(blk1) xor blk2)
i.e. MAC(blk1) = blk2 xor singleblk
'''
_tagprev = hex(singleblk ^ blk2)[2:].zfill(32)
print("Previous tag: ", _tagprev)
tagprev = binascii.unhexlify(_tagprev)
cipher = AES.new(key, AES.MODE_CBC, IV = binascii.unhexlify('0'.zfill(32))) # use AES CBC
blk1 = (cipher.decrypt(tagprev)).hex().zfill(32)
print("Single Block Message: ", hex(singleblk)[2:].zfill(32))
print("Block 1 of two-block Message: ", blk1)
print("Block 2 of two-block Message: ", hex(blk2)[2:].zfill(32))
ex4_verify(blk1, hex(blk2)[2:].zfill(32), _tag, _tagprev, hex(singleblk)[2:].zfill(32))
def ex4_verify(check_blk1, check_blk2, check_tag, check_tagprev, check_singleblk):
key = key = "00000000000000000000000000000001".zfill(32)
tag = check_tag.zfill(32)
tagprev = check_tagprev.zfill(32)
singleblk = check_singleblk.zfill(32)
blk1 = check_blk1.zfill(32)
blk2 = check_blk2
key = binascii.unhexlify(key)
tag = binascii.unhexlify(tag)
tagprev = binascii.unhexlify(tagprev)
singleblk = binascii.unhexlify(singleblk)
blk1_blk2 = binascii.unhexlify(blk1 + blk2)
cipher = AES.new(key, AES.MODE_CBC, IV = binascii.unhexlify('0'.zfill(32))) # use AES CBC
check1 = cipher.encrypt(singleblk).hex()
cipher = AES.new(key, AES.MODE_CBC, IV = binascii.unhexlify('0'.zfill(32))) # use AES CBC
check2 = cipher.encrypt(blk1_blk2).hex()
if check1 == check2[32:]:
print("Tag is the same for ", singleblk.hex(), " and ", blk1_blk2.hex(), ".")
print("Tag: ", tag.hex())
```
Results
```
Key: 00000000000000000000000000000001
Tag: 11fa92774478f2d8fc78756eaa0a1fb5
Previous tag: 0f87e3b053400b58a55239384065d87a
Single Block Message: 0f87e3b053400b58a55239384065d87b
Block 1 of two-block Message: 5f3e639ffb8736012b19a1a525246609
Block 2 of two-block Message: 00000000000000000000000000000001
Tag is the same for 0f87e3b053400b58a55239384065d87b and 5f3e639ffb8736012b19a1a52524660900000000000000000000000000000001 .
Tag: 11fa92774478f2d8fc78756eaa0a1fb5
```
## Exercise 5
Let MAC(.) be the function using CBC=MAC that generates the tag for a message, such that $MAC(a) = t$
The two-block message would be $a || (a ⨁ MAC(a))$.
$MAC(a || (a ⨁ MAC(a)))$ =
= $MAC(MAC(a) ⨁ (a ⨁ MAC(a)))$
= $MAC(MAC(a) ⨁ MAC(a) ⨁ a)$
= $MAC(a)$
= $t$
In other words, by concatenating a with a ⨁ MAC(a), the corresponding tag is still t. The attacker can therefore choose the two-block message as a || (a ⨁ MAC(a)) and forge the tag as t.
In fact, we could continue concatenating more of a ⨁ MAC(a) and apply CBC-MAC and still arrive a tag t. In each XOR operation, the MAC(a) component of the newly concatenated block cancels out t from the previous MAC(.) output. This leaves the final MAC(.) with input a effectively, creating an output equal to t (that the attacked had earlier received).