Information Security

Homework: 0 1 2 3 4 5 6 7

Assignment 2: Encrypted Sockets

Logistics

Your solution should be a zip-file containing two things: your source code (any files you modified or created), and a report that describes what you did and why. The report should be an HTML file named index.html. (It may contain links to other files, if you include those files in your submission.)

You must work in a group on this assignment. You may not collaborate with anyone outside your group.

Introduction

At present, chat clients communicate with the chat server via ordinary network connections. No crypto is used, so anybody with access to the network can eavesdrop on these connections, or tamper with or forge traffic. Your job in this assignment is to solve this problem, by adding appropriate use of crypto, so as to protect the confidentiality and integrity of message traffic.

You will implement your solution by modifying the file SecureSocket432.java, which we have provided to you. You will probably want to create one or more new source code files as well.

The Code

All communication between chat clients and the server takes place via code in the SecureSocket432.java file. Roughly speaking, this code works as follows. First, an ordinary (unencrypted) socket connection is created.

Second, a cryptographic key exchange protocol is executed. This is done by having the programs on both ends of the socket call the keyExchange() method. When this method finishes, it returns a "symmetric key" that is the same on both ends of the socket. (At present, keyExchange uses a highly insecure algorithm, but don't worry about that at this point -- you'll be fixing it in Assignment 4.)

Once both sides have the identical symmetric key, they both call the setupStreams() method, to set up the appropriate encrypted Input/OutputStreams that they will use to communicate. The job of setupStreams() is to initialize variables, called "in" and "out", to point to the encrypted streams.

At present, setupStreams is highly insecure -- it just uses the (unencrypted) Input/OutputStreams of the underlying ordinary socket. You need to fix this.

You'll probably want to do this by creating two new classes of your own, extending the existing java.io.InputStream and java.io.OutputStream classes. Then you can have setupStreams() set the "in" and "out" variables to point to properly initialized versions of your new classes.

Goal

Your goal is to modify SecureSocket432.java, and add any other needed code, so that an adversary cannot learn the contents of chat sessions, cannot forge chat messages, and cannot modify messages without the modifications being detected. Of course, your solution must allow users to chat.

There are several good ways to solve the problem.

Threat Model

The adversary's "wins" if he can do any one of these things: You should make the following assumptions:

Note that your design need not recover from message tampering or message injection. It is enough to detect that one of these events has occurred and then raise an alarm.

Your Report

Your report should describe your solution, and justify why it prevents the adversary from achieving any of his goals. Your report should be concise but should be as convincing as you can make it. The quality of your report will be a very important component of your grade, so pay at least as much attention to your report as to your code.

Helpful Hints

You will probably find the HashFunction.java and/or BlockCipher.java files useful. Remember that these are the only cryptographic primitives you are allowed to use (except for higher-level primitives that you build yourself on top of these two).

Buggy crypto code often causes data to end up totally garbled at its destination. This often causes message receivers to freak out and give weird error messages. So if you try to run the chat service on top of your crypto code, and the result is a bunch of weird error messages, it may be that your decryption process isn't undoing what your encryption process did. You may want to test your encryption and decryption transforms with simple test programs before you try hooking them up to the full chat application.

You may find yourself wanting to buffer up some input or output data. The java.io.ByteArrayOutputStream and java.io.ByteArrayInputStream classes are useful for buffering.

If you write an OutputStream subclass, think carefully about its flush() method. Bear in mind that you are allowed to buffer output data until somebody calls flush(); but when flush() is called, you are obliged to output everything you have buffered. The chat software uses flush() carefully. If you're not careful about your flush() behavior, data may seem to disappear mysteriously in transit (when it is really stuck in a buffer somewhere).



Copyright 2000-2003, Edward W. Felten.