Lab 5: Diffie-Hellman Wisdom

In this lab you will expand your fortune client from the previous lab to include a Diffie-Hellman key exchange.

Your task

Your instructor will provide you with a hostname and port where you can find a fortune server that requires you to perform a Diffie-Hellman key exchange.

When the client first connects to the server, they perform a Diffie-Hellman key exchange in order to agree on a 128-bit symmetric key. Then, the server uses the key to encrypt a fortune (and a flag) with AES in ECB mode, and transmits it to the client. An ordered list of events is as follows:

References

  1. Take a look at the socket api for Python. (The link is is for Python 3.6, but you can change the version in the upper left of the page.)
  2. Take a look at the pycrypto api. It includes an implementation of AES.

Hints

  1. Socket programming is a big topic, so here is some sample code to open a new connection to a given port, read some bytes, and print them:
    import socket
    sock = socket.create_connection(('rainmaker.wunderground.com', 23))
    data = sock.recv(8192)
    print(data)
    sock.close()
    
  2. Note that recv(num_bytes) will receive at most num_bytes, but may return less. If you want to make sure you get a specific number of bytes, you may need to build a loop to do so. (Although frequently you are just lucky and get the number of bytes you expected…)
  3. If you call recv() and there is no data available to be read, then it will block and your program will wait until there is data to be read, the connection is closed, or a timeout occurs.
  4. When passing a key to the pycrypto library, you should be passing raw bytes. For example, a 128-bit key (16 bytes) should be a 16-byte buffer containing the bytes, not an integer.
  5. RFC 3526 specifies the following values for p and g:
    p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF
    g = 0x2
    
  6. You can convert an integer to a hex string using hex()
  7. You can convert a hex string to an integer using int("0x1a2b34", 16)
  8. You can convert a hex string to a byte array using bytes.fromhex("1a2b34") (Python 3) or "1a2b34".decode("hex") (Python 2)
  9. Need to generate some random bits? Check out getrandbits in Python.
  10. Need to do modular exponentiation? Checkout pow in Python.