This is an old revision of the document!
Perform the DH key exchange between two teams, sending the public key values over the network and verify that you get the same secret key.
Use the secret key to encrypt some data (see previous labs) and check that the other party can decrypt it.
Generate a 1024 bit RSA key pair.
Write an oracle function that uses the private key to answer the question “is the plaintext of this message even or odd” (is the last bit of the message 0 or 1). Imagine for instance a server that accepted RSA-encrypted messages and checked the parity of their decryption to validate them, and spat out an error if they were of the wrong parity.
Anyways: function returning true or false based on whether the decrypted plaintext was even or odd, and nothing else.
Take the following string and un-Base64 it in your code (without looking at it!) and encrypt it to the public key, creating a ciphertext:
With your oracle function, you can trivially decrypt the message.
Here's why:
That means the plaintext is less than half the modulus.
You can repeatedly apply this heuristic, once per bit of the message, checking your oracle function each time.
Your decryption function starts with bounds for the plaintext of [0,n].
Each iteration of the decryption cuts the bounds in half; either the upper bound is reduced by half, or the lower bound is.
After log2(n) iterations, you have the decryption of the message.
Print the upper bound of the message as a string at each iteration; you'll see the message decrypt “hollywood style”.
Decrypt the string (after encrypting it to a hidden private key) above.
Alice wants to share a secret with Bob, but she knows that if she explicitly tells it to Bob, Eve somehow will find out (she hears everything). So she and Bob establish a small game which helps them think about the same secret, without saying it. The game goes like this:
$\mathsf{Puzzle}_i = \mathsf{AES}(\mathsf{key} = 0^{14} \| i, \mathsf{plaintext = Puzzle} \| i \| secret_i)$ where $secret_i$ represents the $i$-th secret Alice generated (represents 8 randomly generated bytes) and which should be figured out by Bob.
In the end, both Alice and Bob share the same secret, and Eve has no clue about it.
Your job is to implement this mechanism starting from the following skeleton:
import random import string from Crypto.Cipher import AES import os def aes_enc(k, m): """ Encrypt a message m with a key k in ECB mode using AES as follows: c = AES(k, m) Args: m should be a bytestring multiple of 16 bytes (i.e. a sequence of characters such as 'Hello...' or '\x02\x04...') k should be a bytestring of length exactly 16 bytes. Return: The bytestring ciphertext c """ aes = AES.new(k) c = aes.encrypt(m) return c def aes_dec(k, c): """ Decrypt a ciphertext c with a key k in ECB mode using AES as follows: m = AES(k, c) Args: c should be a bytestring multiple of 16 bytes (i.e. a sequence of characters such as 'Hello...' or '\x02\x04...') k should be a bytestring of length exactly 16 bytes. Return: The bytestring message m """ aes = AES.new(k) m = aes.decrypt(c) return m alice_keys = [] bob_key = [] # TODO This is Alice. She generates 2^16 random keys and 2^16 puzzles. # A puzzle has the following formula: # puzzle[i] = aes_enc(key = 0..0 + i, plaintext ="Puzzle" + chr(i) + chr(j) + alice_keys[i]) # This function shall fill in the alice_keys list and shall return a list of 2^16 puzzles. def gen_puzzles(): # TODO # TODO This is Bob. He tries to solve one random puzzle. His purpose is to solve one random puzzle # offered by Alice. # This function shall fill in the bob_key list with the secret discovered by Bob. # The function shall return the index of the chosen puzzle. def solve_puzzle(puzzles): # TODO def main(): # Alice generates some puzzles puzzles = gen_puzzles() # Bob solves one random puzzle and discovers the secret x = solve_puzzle(puzzles) print "Bob's secret key: " + bob_key[0] # Alice receives the puzzle index from Bob and now knows the secret print "Alice's secret key: " + alice_keys[x] # The secret should be the same, even if it was not explicitly shared if bob_key[0] == alice_keys[x]: print ":)" else: print ":(" if __name__ == "__main__": main()