Assignment Three: Authenticated Channel

In this assignment, you will combine all your previous cryptographic primitives into a functional and secure client-server communication channel over an insecure channel. As in the previous assignments, we will give you some of the code you need, and you must implement functionality to complete the assignment requirements. The following files are provided for you:

File Name Description
a2.jar This is a java archive file containing compiled solutions to the previous assignments. It is highly recommended that you add this file to your classpath and use the solutions within it instead of the .java files from the previous assignment.
AuthDecryptor.java This is a partially implemented class that must perform authenticated decryption (paired with AuthEncryptor). You must add code to implement the methods that are marked with IMPLEMENT THIS. Your additions must work as described below and provide the required security guarantees.
AuthEncryptor.java This is a partially implemented class that must perform authenticated encryption (paired with AuthDecryptor). You must add code to implement the methods that are marked with IMPLEMENT THIS. Your additions must work as described below and provide the required security guarantees.
ChannelTest.java Demonstrates a working test for an insecure channel using InsecureChannel.java. You should use this to help you understand how to use the interface provided by these channels.
InsecureChannel.java This is a class that establishes an insecure communication channel between two participants. This will be the “insecure channel” over which your “secure channel” will send messages.
InsecureChannel.java.debug This is a special version of InsecureChannel that will print messages to the command line for debugging help. To use this class, simply rename it to InsecureChannel.java and recompile your project.
SecureChannel.java This is a partially implemented class that will provide an interface to communicate securely between a client and a server over an insecure channel. You must add code to implement the methods that are marked with IMPLEMENT THIS. Your additions must work as described below and provide the required security guarantees.
SecureChannelTest.java This tests the basic functionality of your SecureChannel. It does not test security properties. You can see the commented sections for examples of how to debug your code.
Util432s.java This file provides a few methods to help with testing and debugging. Feel free to use it during your own tests.

AuthEncryptor.java

Your authenticated encryption class will implement the following API:

public class AuthEncryptor {
    public AuthEncryptor(byte[] key);
    public byte[] authEncrypt(byte[] in, byte[] nonce, boolean includeNonce);
}

This class will perform authenticated encryption on values in byte arrays. Authenticated encryption protects the confidentiality of the values, so that the only way to recover the initial value is to decrypt the value using the same key and nonce that were used to encrypt it. Additionally, authenticated encryption protects the integrity of a value, so that a party possessing the original key and nonce can verify that the value has not changed since it was encrypted.

Code that uses AuthEncryptor must never call authEncrypt using a previously used nonce. The AuthEncryptor class is not responsible for detecting violations of this requirement.

If includeNonce is true, then the nonce should be appended to the output of authEncrypt. If includeNonce is false, then the nonce should still be used in the encryption and authentication, but not appended to the output.

AuthDecryptor.java

Your authenticated decryption class will implement the following API:

public class AuthDecryptor {
    public AuthDecryptor(byte[] key);

    public byte[] authDecrypt(byte[] in);
    public byte[] authDecrypt(byte[] in, byte[] nonce);
}

The value passed to authDecrypt as in will normally be the output of a call to AuthEncryptor.authEncrypt, using the same key and nonce. The AuthDecryptor must verify the integrity of the input value. It must be able to detect whether or not the the input value has changed since being encrypted using the same key and nonce. If the integrity cannot be verified, then authDecrypt returns null. If the integrity is verified, then it will return a newly allocated array containing the original plaintext value that was encrypted by the AuthEncryptor.

SecureChannel.java

Your secure channel class will implement the following API:

public class SecureChannel extends InsecureChannel {
    public SecureChannel(InputStream inStr, OutputStream outStr, PRGen rand, boolean iAmServer, RSAKey serverKey) throws IOException;

    public void sendMessage(byte[] message) throws IOException;
    public byte[] receiveMessage() throws IOException;
}

The constructor of this class will contain the majority of its implementation code. The role of the constructor is to initialize a secure channel in a way that ensures sendMessage and receiveMessage can properly operate. These methods should provide authenticated encryption for messages that pass through the channel, ensuring that messages arrive in the same order as they were sent. Furthermore, when the client is initializing its connection to the server, it should also verify the identity of the server in a way that will detect any potential man-in-the-middle. If either party detects any security problems during initialization, that party should call close() to prevent any further messages from being sent. To ensure forward secrecy, the close() method must also delete any secret values associated with the channel.

The underlying InsecureChannel will normally deliver messages in the correct order, but note that an adversary may try to reorder messages. The receiveMessage method should return null if it receives an invalid or out-of-order message. If a party calls readMessage or receiveMessage when no messages have been sent, it will block/wait until a message arrives.

Threat Model/Report

You are required to submit a short writeup of your design considerations (see Getting Started). This report should succinctly demonstrate that you have considered both the threats against your implementation and the specific techniques you use to defend against them. One way to format this is to describe a threat in a sentence or two, followed by a sentence or two that explains how your implementation defends against it; repeating this format for each threat.

Getting Started

  • Start by looking at ChannelTest.java, which will provide some examples of how the Channel classes should be used. In particular, two instances of a channel are created (one for the client-to-server direction and one for the server-to-client direction). Each channel has two streams (one for sending and one for receiving). Messages are sent through the channel using the sendMessage method. Whenever a message is sent through a channel, it will stay “pending” until the other end calls receiveMessage.
  • Try running the tests with the InsecureChannel.java.debug set up to print the messages as they are sent.
  • Look at the SecureChannelTest.java file to see how an instance of SecureChannel is different.
  • Read through the skeleton code and comments to start understanding what the interfaces look like.
  • Design a threat model. Carefully consider everything that your adversary may try to do and how you might prevent it. This should guide your implementation.
  • Once you are comfortable with your threat model, recall all of the tools available from Assignments One and Two in addition to other basic cryptographic techniques discussed in lecture. This will help you solidify your threat model with more threats and specific techniques to defend against them.
  • You should now have a plan of which cryptographic tools/techniques/machinery you will need and how they should fit together to provide you with the security properties you need.
  • With this plan in mind, start implementing the techniques and configuring them together. Your design should be modular such that each class solve specific problems and can be used in tandem with other classes you’ve created.

Submission Requirements

Submit the following files to Gradescope:

  • report.txt - Threat model and mitigation description.
  • AuthEncryptor.java - Source code file containing your fully implemented authenticated encryption class.
  • AuthDecryptor.java - Source code file containing your fully implemented authenticated decryption class.
  • SecureChannel.java - Source code file containing your fully implemented secure channel class.