Project: 127A Encryption Algorithm


Collaboration: Pair or solo. Everyone must sign up to receive 100% for Quiz 6. That means if you are solo, complete the Google form with "Your name" and "Solo". If you have a partner, both you and your partner must complete the Google form entering your name before your partner's name.

http://goo.gl/forms/zoSrtToK3L

One of our 127A students has been asked by his Iranian employer for a way to send messages around Iran in such a way that no one can read them except someone with the top secret knowledge. Our 127A student did use similar algorithms while he served our country in the Navy. However he cannot use those same Top-Secret algorithms now. That would be treasonous resulting in jail time. This project is loosely based on a true story. If you see John Stewart's movie Rosewater, you might understand the need for secret messages in Iran.

Our task is to come up with a way to encrypt text in such a way as to make the messages unreadable to everyone except those with the code to decrypt those messages back into the original message. How we keep this posted project secret is beyond our comprehension, but at least we will not be giving away a top secret unless this is the same algorithm used by U.S. Naval ships at sea to send encrypted messages. We think not. CSc 127A Section Leaders, Rick, and a spy from the NSA whose name we cannot reveal invented the encryption and decryption algorithms described below.

You mission, should you chose to accept it, is to write these three methods in class Encryption127A

public class Encryption127A

// TODO: Add needed instance variables here

// This constructor initializes the instance variables

public Encryption127A (String original, int[] keys) {

// TODO: Complete this method

}

// Convert the original string into a cipher to prevent unauthorized access

public String encrypt() {

// TODO: Complete this method

}

// Decode encrypted string back to the original message

public String decrypt(String encrypted) {

// TODO: Complete this method

}

}

An Encryption127A encrypt object will be constructed with a String, which could be very long, and an array of keys that may change on a daily or even hourly basis to make it even more difficult to break the code. In this first example the array of keys has 3 elements, but it could be 2 through 16 in length. The keyValues here are 3, 2, and 1, however each key could be any int in the range of 1 through 100. The keys need not be unique. For example, this array of keys is valid: int[] keys = {24, 17, 24, 17};.

The following code shows the Encryption127A constructor and the two other methods of this class being used:

String original = "abcdefghijkl";

int[] keys = { 3, 2, 1 };

// Construct one object

Encryption127A e1 = new Encryption127A(original, keys);

// Send both encrypt and decrypt messages

String encryptedMessage = e1.encrypt();

String decryptedMessage = e1.decrypt(encryptedMessage);

Each character such as a digit, punctuation mark, space, or other keyboard symbol, falls into a group. A char falls into group 0 if original.charAt(index) % keys.length == 0. A char falls into group 1 whenever original.charAt(index) % keys.length == 1. A char falls into group 2 whenever original.charAt(index) % keys.length == 2, and so on. The groups are numbered 0 through keys.length-1 inclusive.

Group Move The move of one char that does not move by an index amount, but rather by the number of times that char in the specified group is found.

int[] keys An array of integers where the ith element is the number of left "group moves" to make for group i. For example if keys[1] is 2, then we would make two group moves searching for any 2 other characters that are in group 1. For example, when encrypting the first char in the String "abcdeghijkl", we find 'a' is in group 1 because 'a' % keys.length == 97 % 3 == 1. Because keys[1] is 2, do two group moves to the left. The char 'a' moves to index 6 (index 9 was skipped).

| | | | | | |a| | | | | | <- A new array of chars

1 2 0 1 2 0 1 2 0 1 2 0 <- Group Numbers of each char

START END SKIPPED

If the char is in the first group (0), find any other char that falls into the same group that is located keys[0], or 3, group moves to the left. If the char is in the second group with a remainder of 1, find any other char that falls into the same group that is located keys[1] places (2 here) to the left, and so on. For this first example, consider where we put the first char 'a'.

"abcdefghijkl"; // The string to be encrypted

The char 'a' % keys.length == 97 % 3 == 1. So 'a' is in group 1. keys[1] is 2. Find the place to put 'a' where the 2nd char located to the left is in the same group. The 1st place to the left of index 0 ('a' ) is index 9. But go to the 2nd place at index 6.

| | | | | | |a| | | | | | <- A new array of chars

1 2 0 1 2 0 1 2 0 1 2 0 <- Group Numbers of each char
0 1 2 3 4 5 6 7 8 9 10 11 <- Array indexes of a new temp array of chars

"abcdefghijkl"; // The string to be encrypted.

The char 'b' % keys.length == 98 % 3 == 2. So 'b' is in group 2. keys[2] is 1. Find the place to put 'b' where the 1st char located to the left is in the same group. The first place to the left of index 1 ('b' ) is found at index 10.

| | | | | | |a| | | |b| | <- A new array of chars

1 2 0 1 2 0 1 2 0 1 2 0 <- Group Numbers of each char
0 1 2 3 4 5 6 7 8 9 10 11 <- Array indexes of a new temp array of chars

"abcdefghijkl"; // The string to be encrypted.

The char 'c' % keys.length == 99 % 3 == 0. So 'c' is in group 0. keys[0] is 3. Find the place to put 'a': where the 3rd char located to the left is in the same group. The first place to the left of index 2 ('c' ) is index 11. But go to index 8 and then to the third char in the same group at index 5.

| | | | | |c|a| | | |b| | <- A new array of chars

1 2 0 1 2 0 1 2 0 1 2 0 <- Group Numbers of each char
0 1 2 3 4 5 6 7 8 9 10 11 <- Array indexes of a new temp array of chars

The encrypted form of the String original would be "geljhcakfdbi". Could you have broken the code and realized the encrypted method "geljhcakfdbi" was actually "abcdefghijkl"? We think not! And imagine keys as an array of 7 integers ranging from 1 to 99. How would you know that is what we used, or the values in the array of keys? We believe we have a hard to break encryption algorithm.

Decrypt

The way to convert the encrypted string back to the original message occurs with decrypt messages using the encrypted string and the exact same keys, the array of ints stored as an instance variable.

@Test

public void testEncyption() {

String original = "abcdefghijkl";

int[] keys = { 3, 2, 1 };

Encryption127A e1 = new Encryption127A(original, keys);

String encryptedMessage = e1.encrypt();

String decryptedMessage = e1.decrypt(encryptedMessage);

assertEquals("geljhcakfdbi", encryptedMessage);

assertEquals(original, decryptedMessage);

}

We still have to pay attention to the same groupings and number of places to move. However, this time we make group moves to the right instead of to the left.

"geljhcakfdbi"; // The string to be decrypted.

The char 'g' % keys.length is 1. So 'g' is in group 1 and keys[1] is 2. Find the place to put 'g' where the 2nd char located to the right is in the same group. The first place to the right of index 0 ('g') is index 3, the 2nd is 6 (skips index 3).

| | | | | | |g| | | | | | <- A new array of chars

1 2 0 1 2 0 1 2 0 1 2 0 <- Group Numbers of each char
0 1 2 3 4 5 6 7 8 9 10 11 <- Array indexes of a new temp array of chars

The encrypt and decrypt methods should work for any char and for any array of integers passed with a maximum length of 16, and the integer values in the range of 1 through 100 inclusive.

@Test

public void testEncryptWithDecrypt7() {

String original =

"The 1 @#$%^&*()_+=- QUICK brown fox 'jumped' >= 023456789 lazy dogs!";

int[] keys = { 6, 4, 2, 4, 5 };

Encryption127A e1 = new Encryption127A(original, keys);

String encryptedMessage = e1.encrypt();

String decryptedMessage = e1.decrypt(encryptedMessage);

assertEquals(original, decryptedMessage);

System.out.println(original);

System.out.println(encryptedMessage);

System.out.println(decryptedMessage);

}

Output from the above @Test that must pass with your class:

The 1 @#$%^&*()_+=- QUICK brown fox 'jumped' >= 023456789 lazy dogs!

rwQ%'*mno '0Cxod5j2 e7l dfg6=Ts u3#ph8 1>y(@ 4o9!_e &^-$az+ ) U=IKb

The 1 @#$%^&*()_+=- QUICK brown fox 'jumped' >= 023456789 lazy dogs!

Grading Criteria 100pts with 0..5 pts bonus or -10 late penalty

____/ 100 WebCat code and problem coverage score.

+1 bonus for every 6 hours early, up to a max of 5pts, which is different, and kinder

-10 if turned in after 9:00 pm Tuesday and before 9:00 pm Friday, which is different, and kinder