def F(k, x): k1, k2 = split(k) x1, x2 = split(x) y1 = AES(x1, k1) y2 = AES(k1, xor_strings(x2, k2)) return y1 + y2
def E(k, m): if len(m) != block_len * 4: return None m = split(m, block_len) c = [random_string(block_len)] t = ["\x00" * block_len] for i in range(4): c += [AES(k, xor_strings(m[i], c[i]))] t += [AES(k, xor_strings(m[i], t[i]))] return join(c), t[-1]
def encrypt(k, m): if len(m) != block_size: return None m = [None] + split(m, block_size / 4) ce = [random_string(16)] cm = ["\x00" * 16] for i in range(1, 5): ce += [AES(k, xor_strings(ce[i - 1], m[i]))] cm += [AES(k, xor_strings(cm[i - 1], m[i]))] return join(ce), cm[4]
def encrypt(k, x): r = random_string(block_size) c = r for i in range(1, len(x) / block_size + 1, 1): w_i = add_int_to_string(r, i, block_size * 8) x_i = x[((i - 1) * block_size):(i * block_size)] c += AES(k, xor_strings(x_i, w_i)) return c
def encrypt(k, x): """ :param k: The key used to encrypt/decrypt the message :param x: The plaintext to be decrypted :return: return the encryption of plaintext x """ r = random_string(block_len) c = r for i in range(1, len(x) / block_len + 1, 1): w_i = add_int_to_string(r, i, block_len * 8) x_i = x[((i - 1) * block_len): (i * block_len)] c += AES(k, xor_strings(x_i, w_i)) return c
def F(k, x): return AES(k, x) + AES_I(k, x)
from crypto.primitives import AES, AES_I from crypto.tools import * """ Note: Based on exercise in slide 30, PRF lecture. The family of functions F: {0, 1}^128 x {0, 1}^128 --> {0, 1}^128 is defined by: """ # Block & key size in bytes. block_len = 16 key_len = 16 F = lambda k, m: AES(m, k) """ Show that F is not a secure PRF by presenting a practical adversary A such that Adv(prf, F, A) is close to one and makes at most 2 queries to its Fn oracle. Fill in the code for adversary A, verify it's advantage by running your code and describe the running time. """ def A(fn): """ You must fill in this method. :param fn: This is the oracle supplied by GamePRF, you can call this oracle to get an "encryption" of the data you pass into it. :return: return 1 to indicate your adversary believes it is the real world and return 0 to indicate that your adversary believes it is in the random world. """
t += [AES(k, xor_strings(m[i], t[i]))] return join(c), t[-1] def D(k, (c, t)): if len(c) != block_len * 5: return None c = split(c, block_len) m = [] tm = ["\x00" * block_len] for i in range(4): m += [xor_strings(AES_I(k, c[i + 1]), c[i])] tm += [AES(k, xor_strings(m[i], tm[i]))] if tm[-1] != t: return None return join(m) """ 1. [20 points] Give an IND-CPA adversary that shows that this sceme is not IND-CPA secure: """ def A_1(lr): """ You must fill in this method. This is the adversary that the problem is
cm += [AES(k, xor_strings(cm[i - 1], m[i]))] return join(ce), cm[4] def decrypt(k, (ce, t)): if len(ce) != block_size + 16: return None ce = split(ce, block_size / 4) cm = ["\x00" * 16] m = [None] for i in range(1, 5): m += [xor_strings(AES_I(k, ce[i]), ce[i - 1])] cm += [AES(k, xor_strings(cm[i - 1], m[i]))] if cm[4] != t: return None else: return join(m[1:]) """ Give an INT-CTXT adversary that shows that this sceme is not secure: """ def adversary(enc, dec): """ You must fill in this method. This is the adversary that the problem is