Practical Cryptography!
(Well, for the 1600s maybe...)
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!
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.
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.
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:
Plain text: Computer Science Keyword repeated: CMSC131CMSC131CMlet'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.
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.
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
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.