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 thesendMessage
method. Whenever a message is sent through a channel, it will stay “pending” until the other end callsreceiveMessage
. - 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 ofSecureChannel
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.