CMSC 131 - Fall 2019 - Project #2


Suggested target for Task 1: before end of office hours Tuesday, September 24th.
Graded: scan/photo of Task 2 pseudocode/flowchart due on ELMS before 8pm, Thursday, September 26th.
Suggested target for Task 2: before end of office hours Friday, September 27th.
Suggested target for Tasks 3 and 4: before end of office hours Tuesday, October 1st.
Graded: assignment submission due on Submit Server before 8pm on Wednesday, October 2nd.

Type of project: CLOSED

Practical Cryptography!
(Well, for the 1600s maybe...)
cipher symbols

Objective

This project will allow you to practice using loops and String/character processing. You will implement three different but related encoding systems that will allow users to attempt to hide messages written using UNICODE characters (a subset of the UNICODE set) from the blank space (UNICODE 32) to the _ symbol (UNICODE 95). You might want to look to see what the full ASCII part of the UNICODE table looks like. This specified range only contains uppercase letters. In crypto, it was not uncommon to make all letters uppercase as a way to try to make it harder to break a code. In our project, if a person wants to send a message that contains a lowercase letter, we'll turn it into an uppercase letter for them, and then do our encoding based on that.


Overview

This project is composed of four tasks. They should be completed in sequential order. The later tasks build on ideas you will have explored in the earlier ones. The first task has you building a method that will check whether a message's characters are all in the valid range (UNICODE 32 to 95). This will allow you to practice using a for loop to iterate through the characters of a String and using Java operators to have your code interact with individual characters. The next three tasks will have you building methods to support three different, but related, encoding systems. Unlike the first project, each task does not have its own .java file and main method associated with it. All of the methods you need to design and implement are in the same file, CryptoCode.java, and they are static library methods, so will be invoked from other places. We have provided a simple testing driver for you in the ExampleTest.java file, and you are strongly encouraged to modify this with code to help you test and debug things.

We have provided you with a GUI that can be started using Launcher.java from Eclipse. As you work on the project, this GUI will provide an easy way to try out your code. You are encouraged to, at a minimum, check to see whether you are getting the right results for the samples towards the bottom of this description. You will also likely find it useful to come up with smaller examples where you do the encoding/decoding by hand and then verify that your program does the same.

We have also provided you with a short, standalone text-based program that asks the user to enter a single lower-case letter and then shifts the letter by one position and prints the result. We strongly encourage you to start off by reading through that code, running the program, and trying a few scenarios to get a feeling for how that code works and why. It can also serve to provide some ideas in terms of both problem solving and Java syntax that will be of use as you are working on the project. The example is in the exampleCode subfolder, in a file named SingleShift.java. If you have questions about this, it is something you can ask about in office hours.

This project is a CLOSED individual assignment. That means, among other things, that you are not allowed to try to get help on this from anyone other than our TAs or me in office hours. You may come to office hours to ask us questions of course. Please visit the course web page for information regarding the open/closed policy for projects of this course for more details.


Specifications

chatAt() and length()
This project will make extensive use of the .charAt(int) and .length() instance methods of the String class and character "math" to shift letters backwards and forwards within a subset of the UNICODE character set. Before you attempt to write any code of your own, you should read through and make sure you are comfortable with all of the code within the main method of the SingleShift.java example code that is in the starter project files from CVS.


Task 1
The first task has you building a method that will check whether a message's characters (after any lowercase letters have been changed to be uppercase letters) are all in the valid range (UNICODE 32 to 95). This will allow you to practice using a for loop to iterate through the characters of a String and using Java operators to have your code interact with individual characters. There is one method to implement for this task:

     public static boolean safeToUse(String plaintext)
The parameter plaintext will refer to a String object. Your code will need to iterate through this character by character and make sure each one is valid to be used in our coding schemes. If any of the characters are outside the valid range, then the method returns false. Recall from above that the range of valid characters for this project doesn't contain any lowercase letters. This means that the first thing we'll probably want to do to the plaintext is convert it to uppercase-only. You should find the .toUpperCase method that all String objects can invoke quite useful here!

Once you have an uppercase-only version of the message, use a for loop and something like the .charAt(position) method that can be invoked by any String object to iterate through the message character by character. As you visit each character, make sure that its UNICODE value isn't outside of the valid range. Note that in the provided starter code, we've provided some static constants:
	static final char LEFT_BOUNDARY = ' ';
	static final char RIGHT_BOUNDARY = '_';

	static final int RANGE = RIGHT_BOUNDARY-LEFT_BOUNDARY+1;
You might find these useful as you develop your code for this project, either in this task or in others.


Task 2
This task will have you implementing a very simple (and very easy to break) encoding system, but the concepts you use to do so are at the heart of more advanced ones as well. Again, you should be sure to read through the SingleShift sample code before working on this to familiarize yourself with some Java syntax and problem solving approaches that will be useful here. The core idea was actually used in early online discussion groups as a way to make a post unreadable at first glance, but easy to decode once a person decided they wanted to read it. Our Task 2 system is called Rot32. Since there are 64 valid characters in this project when it comes to messages, one way to easily encode and decode a message is to "rotate" each character by 32 positions. This means that the same algorithm can be used to encode and to decode messages. It also means that as soon as someone knows our approach, all of our messages can be instantly decoded by the enemy.

One subtle point is that you need to rotate "around" the end of the valid UNICODE range. For example, the letter H has an UNICODE value of 72. When you add 32 to this you get 104. However, we said we'd only be using characters between UNICODE positions 32 and 95. The way we handle this is that if the new value is greater than 95, we simple "wrap around" to the start of our range. To do this, we can subtract 64 (the range of values we have) from the number, and we will have essentially have "wrapped around" the valid character list. We now have 40, which is ( in UNICODE.

Using this system, the message
   Hello class
would first need to be changed to
   HELLO CLASS
and then encoded as
   (%,,/@#,!33.

Work this out by hand using the ASCII part of the UNICODE table to make sure you are comfortable with the idea. There is one method to implement:

    public static String rot32(String message)
The parameter message will refer to a String object. Your code will need to iterate through this character by character, "rotate" that character by 32 positions, and then use it as part of a new String that you will return at the end of the method. Don't forget that we will only be using upper-case letters! Once again, you might find the .toUpperCase method that all String objects can invoke is useful. Then, take this algorithm and hand write the pseudocode or Java code that you think would accomplish this "rotate 32" task. Trace though that code by hand with the Hello class example and make any corrections you think are needed. Then, take a photo or scan of your final handwritten pseudocode or Java code (not the trace of Hello class) and upload it to us on ELMS by the deadline for that part of the project.

Now, go ahead and code this up in Eclipse and test it out! If you find you need to make corrections, that's fine. You should not go back and redo your drawing and ELMS submission. However, make sure that you are comfortable with the reasons for why you made the changes you did to get this task working right, you'll find the concepts critically useful in the next two tasks.


Task 3
The system in the previous task had a fatal flaw. As soon as the enemy learns of our system, they can break every message of ours. In this task, we will "up our game" a little, and implement what's known as the Caesar Cipher. The core idea is that two people will agree in advance on a number (between 0 and 63 makes the most sense in the case of this task, but if someone chooses a larger number your code needs to be able to handle it correctly) and then to encode a message, rotate each character forward that number of positions (with wrap-around if needed), and to decode a message, rotate each character backward that number of positions (again, with wrap-around if needed). If the person picks a number greater than 63, we'll just keep subtracting 64 from that until we get a value in the valid range (so if they pick 131 we'd subtract 64 and get 67 which is still too big so subtract 64 again and get 3 which we would then use as the shift amount). When you think about it, the Rotate 32 system is actually just a special case of the Caesar Cipher, where the agreed-upon number is always 32.

For this task, there are two methods to design and implement:

         public static String toCaesar(String plaintext, int shift)
and
         public static String fromCaesar(String ciphertext, int shift)
Each takes a String and an integer. The integer represents the agreed-upon shift amount in both cases. The String is either the plaintext form of the message or the ciphertext version. Each method returns the encoding/decoding of the String it got, as indicated by the method name.

The toCaesar method will need to "shift and wrap" forward. For example, if the message had an H and the agreed-upon shift were 7, the H (UNICODE 72) would become an O (UNICODE 79) since 72+7 is 79. If the message had a Z and the agreed-upon shift were 7, the Z (UNICODE 90) would become a ! (UNICODE 33) due to the wrap-around; 90+7 is 97 which is outside the valid range so we need to subtract 64 from that to effectively "wrap around" the valid range, which gets us 33.

Similarly, the fromCaesar method will need to "shift and wrap" backward. For example, if the coded message had an O and the agreed-upon shift were 7, the O (UNICODE 79) would become an H (UNICODE 72) since 79-7 is 72. If the message had a # and the agreed-upon shift were 7, the # (UNICODE 35) would become a \ (UNICODE 92) due to the wrap-around; 35-7 is 28 which is outside the valid range so we need to add 64 to that to effectively "wrap around" the valid range, which gets us 92.

The code you designed and implemented in Task 2 should provide a very strong start to this task. Once you have this working, you have a cipher system where your enemy can know that you are using the system, but as long as you have a secure way to have two people agree on a shift, knowing it's a Caesar Cipher doesn't instantly allow the enemy to read your messages. So, this is a step up from the Rotate 32 cipher.


Task 4
Sadly, the Caesar system is also weak. There are two ways that it can be broken. First, if you know the language of the message (such as English) then you can use character frequency analysis to break any encryption scheme that does simple substitutions, which is what Caesar effectively does. Additionally, since there are only 64 unique shift values, with modern computing it would be trivial for an enemy to hire a good coder to write a program that would try all 64 and determine which created a readable result. This brings us to Bellaso!

Giovan Battista Bellaso was an Italian lawyer in the 1500s who was quite adept at mathematics. He was also a secretary who explored cryptography as a way to securely transmit correspondences about state affairs!

One of the systems he developed was an enhancement of the shift cipher. Rather than use a single shift, it used many. These shifts were represented by a keyword. For example, imagine a message Computer Science and a keyword CMSC131. There are two parts to this cipher system as you will implement it:

  • the keyword is repeated until its length matches the length of the message - in this case, that would be CMSC131CMSC131CM
    (NOTE: You will need to convert the keyword to uppercase letters if it has any lowercase letters before using it for the encryption.)

  • the character from the repeated keyword that lines up with a character in the message is used as the shift by making the shift be that character's UNICODE value minus the ASCII/UNICODE value of the first valid character in our range, which in this case is 32 (note that this ends up making the valid shift values go from 0 through 63)
  • Using the example:
       
          Plain text:       Computer Science
          Keyword repeated: CMSC131CMSC131CM
    let's look at how we would encode the i. We would have first converted the lowercase i to an uppercase I using the .toUpperCase() method. The UNICODE value for I is 73. The shift keyword tells us that we'll be shifting according to the character 1 (note, the character 1 not the numeric integer 1). Note that that character 1 has the UNICODE value of 49, which according to the above rules tells us the shift amount will be 17 (49-32). Remember, this is because the ASCII/UNICODE value for the first valid character in our range is 32. So, 73+17 gives us 90, which is the UNICODE value for Z.

    We now have a far more advanced cipher system that appears immune to frequency analysis (since different shifts are used for different positions, which means that in the above example, a & in the ciphertext represents a C from the plaintext at one point and a U from the plaintext at another point).

    For this task, there are two methods to design and implement:
             public static String toBellaso(String plaintext, String keyword)
    and
             public static String fromBellaso(String ciphertext, String keyword)
    Each takes a String for the message text and another String for the cipher keyword. Your experience and learning from the earlier tasks will greatly inform your work on this one.

    To prevent possible user error, any letters in the ciphertext passed into the fromBellaso method will need to be forced into uppercase even if they were lowercase as typed into the GUI.

    After you have implemented the methods for this task and tested them and have passed all of the submit server tasks, you might want to think about how easy or hard this system would be to break.


    Getting Started

    In order to help you get started, for each task we have created a different method skeleton in the CryptoCode.java file in which you will work. When you first check out the project, there will be comments to help guide you within that file. Also, each method you will work on starts with

         throw new RuntimeException("You need to design and implement this!");
    
    inside it. When you are ready to implement a method, you will replace this line of code with your implementation. All of these are retrieved by checking out the project from the CVS repository. Remember that you must have set up your repository in order to check out and submit projects.  Start by going to your CVS repository and checking out project Fall2019-Proj2. After checking out the project, when you switch back to the Java perspective, you will see the above files in the "Package Explorer" window, and you will be able to start modifying them.

    If you write the project from scratch, without checking out the "Fall2019-Proj2" files from your CVS repository, you will NOT be able to submit your work and you will NOT get credit for it.


    Requirements

     

    Sample Encoding/Decoding

    The following examples show how some messages will look when encoded using the different cipher strategies.

    Rot32 Example
    The message is:  CMSC 131
    The coded message is:    #-3#@QSQ

    Caesar Example
    The message is:  Computer Science
    The shift is:  131 (which your code will reduce to 3 due to our 0 to 63 restriction)
    The coded message is:    FRPSXWHU#VFLHQFH

    Caesar Example
    The message is:  a
    The shift is:  100 (which your code will reduce as well due to our 0 to 63 restriction)
    The coded message is:    %

    Bellaso Example
    The message is:  Computer Science
    The keyword is:  CMSC131
    The coded message is:    &<@3&'V5MF&ZX_&2

    Bellaso Example
    The message is:  Greeting Humans.
    The keyword is:  MarsRulez!
    The coded message is:    4378F>:,ZIB.3AE#

    REMINDER: Each of the Caesar and Bellaso gives you two examples to test out - one for encrypting and one for decrypting.

    NOTE: While invalid text will be sent in to the safeToUse method as part of testing, for this project you can assume that any text send to the methods rot32, toCaesar, fromCaesar, toBellaso, fromBellaso will be valid.


    Pseudocode/Flowchart

    The scan/photo of pseudocode/flowchart assignment for this project is associated with Task 2. After you read the task and think about the algorithm, hand write the pseudocode or Java code that you think would accomplish that "rotate 32" task and trace though that code by hand with the Hello class example and make any corrections you think are needed. Then, take a photo or scan that and upload it to us on ELMS before 8pm on September 26th. It can be a jpg, gif, or pdf file. This will be worth 10% of your project grade. Please note your pseudocode/flowchart doesn't have to be perfect to get full credit, it just needs to reflect that you have read the task description and have thought about the structure of the Java code you will be writing, and traced it on the example.


    Project Submission

    Submit your project from Eclipse by right-clicking the project folder and selecting "Submit Project".  You are encouraged to submit as you complete each task (or think you have completed it). This means you have run the program for a task and tested it out yourself and think it's ready to pass our tests. We we only grade your most recent submission (before the deadline) so there's no penalty for mistakes the submit server reveals if you then fix them before the due date. After you have submitted a version of your project, you then need to visit the submit server to obtain (limited) feedback about how well your project is performing. (Choose "release test" to see detailed information.) While the public tests can be run as often as needed (within logistical reason of course) the number of times you can run our release tests on your project (before the due date) is limited so the earlier you begin working on the project, the more opportunities you will have to see how your project performs on our tests before the due date!


    Grading

    There are 8 public and 6 release tests which will be run on your project and which you should check yourself as you complete each phase of the project. Different tests will be worth different amounts of points. Some tests might test not only what your program does, but how it does it. Please note that some of the release tests will test multiple scenarios within them and will not have partial credit within that test. Together, these tests will determine 90% of the grade on the project. 





    Web Accessibility