SE-2811 Software Component Design
Lab 2: A Strategy-based File Encrypter

The submission page is now available at esubmit.msoe.edu. If off-campus, you must use Global Protect, which you should check if you have installed now if you work on labs off campus. The Esubmit Instructions page gives an overview of how the esubmit checks work and links the files it uses.

In this lab you will use the strategy pattern to build a tool to encrypt and decrypt text files. This tool would be used in a bigger system to provide secure communication between two parties, where each set of parties would have their own particular encryption and decryption settings. The primary class you will implement is CipherMessage; it will contain Encrypter objects to handle encrypting and decrypting messages.

 

You will also write a short program using this class to encrypt and decrypt data. This program will serve as a test bed to ensure that your implementation is correct. In a full implementation, you would have tables matching parties to particular CipherMessage objects. For this lab, you do not need to implement these tables.

All interaction with the user is through standard input and output (System.in, System.out). Do not implement a GUI or use GUI operations like JOptionPane. On start up, your program will prompt the user for the input file, whether to encrypt or decrypt the data, and the corresponding output file. For example, if you encrypt abc.txt to abc.xor using the key "what", your program will interact with the user as

Input: abc.txt
Output: abc.xor
Encrypt (y/n): y
Method (rev, shift, xor): xor
Key: what
Encrypted abc.txt to abc.xor using xor

where the bold text is the parts entered by the user. Some notes on the interaction:

CipherMessage is to read all the bytes from the input file and write the appropriate bytes to the output file depending on the operation selected by the user.

Note that the encryption algorithms are fairly simple (and thus not very secure compared to encryption techniques that are actually used in actual internet protocols): The ShiftEncrypter encrypts text by simply substituting the another alphabetic character for each character encountered. The index attribute (set by the ShiftEncrypter constructor) affects which character is substituted. For example, when index=1, ShiftEncrypter's encrypt() method would encrypt the 3-byte text Hal to Ibm, while the decrypt() method does the opposite. Similar to a Caesar cipher, if the numeric value of the character would fall outside of the ASCII range (0-255), it should "wrap around" to the other end. For example, if a code would have the numeric value of 256, it should wrap around to 0, and a numeric value of 300 should wrap around to 4.

Similarly, ReverseEncrypter encrypts simply by reversing the bytes in the array to be encrypted; thus Hello there Bob! becomes !boB ereht olleH.

The XorEncrypter is a little more complicated (so slightly harder to crack): For each byte in the array to be encrypted, this encrypter does an exclusive-or (^ in Java) with each successive character in the specified key. For example, if the key is "abcd", then the encrypted array is
H^a   e^b   l^c   l^d   o^a   <sp>^b   t^c   h^d   e^a   r^b   e^c   <sp>^d   B^a   o^b   b^c   !^d, where H^a represents the character that results from applying the exclusive-or to H and a. Note how the bytes in the key array are cycled through. To decrypt an encrypted array, you simply need to apply exclusive-or using the same key to the encrypted array. Note that exclusive-or can easily generate non-printable characters. The last time through the key you may not use all of it.

Both the input and output files of this program follow the format

        size|checksum|message
where size is the number of bytes in message, checksum is the result of adding all of the bytes together as integers, and message is the bytes themselves. The vertical bar is not included in the files. The size and the checksum are both 8-byte fields stored as raw binary numbers. Please review your SE1021 image editor lab for how to read and write binary files in Java.

Read the javadoc for the methods you use to read and write to ensure that they are guaranteed to read and write as many bytes as you expect. Some methods behave similar to a Python socket's recv() method.

Additional Constraints and Notes

Your assignment will consist of:

Note the reverse-engineered diagram is to match your implementation; it may differ in details from the above diagram (often because you have differing associations).

When you are finished, submit your assignment according to your instructor's specific directions.

Your assignment may be automatically tested using a JUnit test framework, so be sure to implement the method signatures exactly as shown in the class diagram for the  CipherMessage, ReverseEncrypter, ShiftEncrypter, XOREncrypter, and the Encrypter classes.

Submission

Submission of the lab will be electronic. Details are still to be announced.