CSE 142, Winter 2022: Assessment 3

Assessment 3: Encryption Machine

Initial submission due Tuesday, January 25, 11:59pm

Objectives

This assignment will assess your mastery of the following objectives:

  • Write a functionally correct Java program to produce specified console output.
  • Use Scanner to accept and process user input.
  • Write for loops, including nested loops, to repeat code and manage control flow.
  • Write and call methods that accept parameters to perform generalized tasks.
  • Use class constants to represent and modify important values in a program.
  • Follow prescribed conventions for spacing, indentation, naming methods, and header comments.

Background

Note: You do not need to read this section to complete the assessment, but it provides some helpful context that may make the assessment easier to understand.

The idea of encryption as a means to hide the meaning of messages has deep roots in history. The first known military use of encryption ciphers was in 100 BCE when Julius Caesar used them to send secret messages to his generals out in the field. In the event that one of these messages got intercepted, his opponents could not read its contents easily. This process of encryption scrambles (in a deterministic fashion) the original message, known as plaintext, into an alternative form known as ciphertext. Today, encryption algorithms help to control data privacy and security all over the world. Algorithms such as RSA and AES are some of the most widely used ciphers that are vital to protect digital security. One of UW's professors, Neal Koblitz, is renowned for creating some of the most secure encryption algorithms today, elliptic and hyperelliptic curve cryptography.

The goal of encryption is to ensure privacy and prevent third parties from reading or modifying secret information. Rather than sending plaintext messages, encrypted messages are sent that can only be decrypted using some previously-agreed-upon process and are unreadable to anyone who does not know this process. In this way, only those who know the decryption process can read the message.

Substitution Ciphers and Cryptographic Keys

Substitution ciphers encrypt text by replacing each character in the plaintext message with another character according to some rule. This rule can be defined or demonstrated by a cryptographic key—a piece of information (in our case, a sequnce of letters from our alphabet) known only by those who are intended to be able to read the encrypted text. In our ciphers, both parties agree on a predetermined key. Then, the key is encrypted and sent to the receipient along with the encrypted message. Since the recipient knows the plaintext of the key, they can determine how the key was encrypted and then use the same process to decrypt the rest of the message.

In this assessment, you will only be responsible for encrypting a provided key and outputting the resulting ciphertext. Our tests will use this key to decrypt your secret message (see below). Your program is not required to handle determining the cipher from an encrypted key or decrypting an encrypted message.

Key Terminology

cipher
An algorithm, or process, for encrypting and decrypting messages
plaintext
The message that will be encrypted by a cipher
ciphertext
The result of running the encryption process on the plaintext; generally unreadable without decrypting
encrypting/decrypting
The process of turning plaintext into ciphertext or vice versa
cryptographic key
A secret piece of information that is known by all parties using the cipher and is used to decrypt encrypted messages

Program Behavior

In this assessment, you will write a program to encrypt a message for secret transmission to another person. Unlike previous assessments, this program's behavior is dependent on input from a user (bold and underlined below). Your output should match our examples exactly when given the same input, but if the input changes, the output should also change. Additional execution logs will be posted on the course website, and you can use the Mark button in Ed to check your output for various inputs.

The program begins with an introductory message that briefly explains the program, then prompts the user to enter a cryptographic key. The program encrypts the key using a Caesar cipher (see below) and prints the ciphertext.

If the plaintext key is known by the recipient of an encrypted message, the encrypted key can be used to determine the cipher used and decrypt the message.

Next, the program asks the user for the number of words in the message that will be encrypted. The program will prompt for that many words and print out the encrypted cipher text for each, one at a time. Each word will consist only of characters from a pre-defined alphabet, and you should use a class constant for the alphabet so that your program can be easily modified to use different alphabets (see below). By default, the alphabet will consist of lowercase English letters only.

Sample program execution
Welcome to the CSE142 Encryption Machine!
The program lets you encrypt a message
with a key so your recipient can decrypt.

Encrypted messages use a shared keyword to decrypt.
  Enter key: cseonefortytwo
    "cseonefortytwo" has been encrypted to: fvhrqhiruwbwzr

How many words are in your message? 4
  Next word: computer
    "computer" has been encrypted to: frpsxwhu
  Next word: science
    "science" has been encrypted to: vflhqfh
  Next word: is
    "is" has been encrypted to: lv
  Next word: awesome
    "awesome" has been encrypted to: dzhvrph

Message fully encrypted. Happy secret messaging!

Caesar Ciphers

Although the Caesar cipher is a substitution cipher, we do not recommend trying to implement a general substitution approach. The specific form of the Caesar cipher allows some things to be easier. See the development strategy below for our suggested approach.

A Caesar cipher is a type of substitution cipher in which plaintext characters in an alphabet are substituted with ciphertext characters generated by shifting each plaintext character a fixed number of positions forward in the alphabet (3 by default). The default alphabet is the set of all lowercase English letters, but you should be able to modify the alphabet. The table below demonstrates how the word "play" is encrypted using this type of cipher.

plain text p l a y
+ shift 3 3 3 3
= ciphertext s o d b

Notice that the cipher will "wrap around" the alphabet as necessary. For example, shifting 'y' by three positions results in 'b'. Here is the full mapping for a Caesar cipher with a shift of three, with the letters in "play" highlighted:

Table showing Caesar shift

Implementing a Caesar cipher

Java allows you to perform arithmetic on characters, but you MAY NOT use this feature on this assessment.

As outlined in the program behavior, plaintext characters are replaced by new characters in ciphertext by shifting each character a fixed number of positions forward in the alphabet (3 by default). To perform this shift, you should use a class constant to help search for the shifted characters. You should have a constant named ALPHABET that represents the alphabet for this program, and a constant named SHIFT that represents the number of characters to shift by (described below). You should calculate a ciphertext character by finding the character that is SHIFT characters ahead of the plaintext character in ALPHABET.

Although the default alphabet contains only lowercase letters in the English alphabet, your program should be able to work with different alphabets by changing the ALPHABET constant. One example we use to test your program is an alphabet that includes digits; i.e. your alphabet would be the string "0123456789". Although the "words" you encrypt with this alphabet will contain only digits, you should still read them in and treat them the same way you would words containing characters in the default alphabet, by shifting the characters SHIFT positions in the ALPHABET string. Your code should not depend on what types of characters appear in the ALPHABET string.

Development Strategy

You will need to have implemented your ALPHABET constant in step 2, but you should not worry about changing its value yet. Just use the default alphabet.

As on Assessment 2, we suggest you approach the program in stages rather than trying to implement everything at once. Specifically, we recommend implementing funcionality in the following order:

  1. Single letter: Write a method to encrypt a specific single letter with a shift of three and print the encrypted letter.
  2. Parameterized letter: Modify your single letter encryption method to be able to encrypt any letter in your alphabet with a shift of three (including wrapping around the alphabet).
  3. Single word: Use your method that can encrypt a single letter to develop a method that can encrypt an entire word one character at a time.
  4. User input: Prompt the user for a key and a message to encrypt and output the encrypted ciphertext.
    Use the nextInt() method in Scanner to get integer input from the user.
  5. SHIFT constant: Add a constant so that you can change the numbers of characters you shift in your cipher.
  6. ALPHABET constant: Test your program with different values for the ALPHABET constant to make sure you can encrypt characters in different alphabets. (Ed will test your code with an all uppercase English alphabet, an alphabet comprised only of digits, and an alphabet that consists of both lowercase English letters and digits.) You should have already implemented this constant, so it's possible that you won't need to do anything extra to make this work.
    Note that your code for wrapping around the alphabet likely depends on the length of your ALPHABET constant. Make sure your program works for values of ALPHABET that have a different length than the default!

Hints

The following hints may help you as you work on this assessment:

  • Remember that you can find the index of a specific character within a String with the indexOf(char) method.
  • Conversely, you can find the character at a specific index within a String with the charAt(int) method
  • To allow for characters wrapping around the alphabet, it might be helpful to think of the alphabet as being circular. Use the mod (%) operator to wrap around!
  • You can use the nextInt() method of Scanner to get an integer value from the user, and the next() method to get a word as a String

Creative Portion (secretmessage.txt)

Along with your program, you should write a "secret" message from you to your TA that should be encrypted by using your program. The message can be anything you want, as long as it does not include hateful, offensive, or otherwise inappropriate speech. Your TA will decrypt your message with your program and read it while grading. This part of the assessment will only contribute to the Behavior dimension grade and will not factor into your grade for the other dimensions.

In order for your TA to decrypt your message, you should use the key "cseonefortytwo" and include the ciphered key with your secret message. You should use the default value for ALPHABET but may use any value for SHIFT that is greater than 0. You should include your ciphered key on one line, and your ciphered message on another line, as shown here:

Sample secretmessage.txt
ENCRYPTED KEY:
mcoyxopyebdidgy

ENCRYPTED MESSAGE:
ywkb sc wi pkfybsdo sxcdbemdyb

To create this file, you should run your program, enter "cseonefortytwo" as the key, and enter whatever secret message you choose. You can then copy the encrypted key and message into the secretmessage.txt file that you submit.

Implementation Guidelines

Like all CSE 142 assessments, this assessment will be graded on all four dimensions defined in the syllabus. Be sure to adhere to the following guidelines:

Required methods

You should use methods, including parameters, to capture structure and remove redundancy in your program. In addition, for this assessment, your program must include a single method to encrypt a word. You can (and should) include additional methods as you see fit.

User input

Do not use the nextLine() method in this program.

Read all user input using a Scanner and the next() and nextInt() methods. You may assume the user always enters valid input when prompted. Specifically, you may assume that:

  • The user will always enter a value of the correct type.
  • The user will only ever enter 1 word when asked for the key or the next word to encrypt.
  • The user will only enter characters in the defined ALPHABET constant (lowercase English letters, by default).

You should use the next() method to read in all words to encrypt, even if your alphabet contains digits and those words consist only of digits.

Class constants

Different values of the ALPHABET constant may include other characters; Ed will test your program with alphabets that include uppercase English letters and digits.

As described above, your program should work under the assumption that the user will use an alphabet of only lowercase English letters by default, but this value should be able to be easily changed. You must introduce a class constant for the alphabet, and use this constant throughout your program to determine what character to shift to. To ensure our testing and grading scripts work correctly, you must name this constant ALPHABET. Please set the value of the constant to its default before submitting your work. By default, your ALPHABET constant should be declared as follows:

public static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";

Your program should also include a constant for the amount to shift each character in the alphabet when encrypting. (The default shift is 3.) To ensure our testing and grading scripts work correctly, you must name this constant SHIFT. Your program only needs to handle non-negative shifts.

Permitted Java Features

For this assessment, you are limited to Java concepts covered in chapters 1 through 3 of the textbook, as well as section 4.3 (but no other part of chapter 4). In particular, you MUST use for loops and parameters, and you may not use if or if-else statements or returns.

Code Quality Guidelines

In addition to producing the desired behavior, your code should be well-written and meet all expectations described in the grading guidelines and the Code Quality Guide. For this assessment, pay particular attention to the following elements:

Capturing Structure

Your program must include the required methods described above, though you may include additional methods if you like. As always, your main method should be a concise summary of the program and your program should not include any trivial methods. You should use static methods to accurately capture the structure of the output in your program. You should not produce any output in your main method.

Parameters

Your program should utilize parameters to define generalized methods that can be used to create various similar results. In particular, your program should include only a single Scanner which is passed as a parameter to all methods that need it. You should NOT declare your Scanner as a constant; you must pass it as a parameter. In addition, your methods should not accept any unnecessary parameters. For this assessment, a parameter is considered unnecessary if its value is unused, is always the same as the value as another parameter, or can be directly computed from the values of other parameters.

Code Aesthetics

Your code should be properly indented, make good use of blank lines and other whitespace, and include no lines longer than 100 characters. Your class, methods, variables, parameters and constants should all have meaningful and descriptive names and follow the standard Java naming conventions. (e.g. ClassName, methodOrVariableName, CONSTANT_NAME) See the Code Quality Guide for more information.

Commenting

Your code should include a header comment at the start of your program, following the same format described in assessment 1. Your code should also include a comment at the beginning of each method that describes that methods behavior. Comments should be written in your own words (i.e. not copied and pasted from this spec) and should not include implementation details (such as describing loops or expressions included in the code). See the Code Quality Guide for examples and more information.

Getting Help

If you find you are struggling with this assessment, make use of all the course resources that are available to you, such as:

Collaboration Policy

Remember that, while you are encouraged to use all resources at your disposal, including your classmates, all work you submit must be your own. In particular, you should NEVER look at a solution to this assessment from another source (a classmate, a former student, an online repository, etc.). Please review the full policy in the syllabus for more details and ask the course staff if you are unclear on whether or not a resource is OK to use.

Reflection

In addition to your code, you must submit answers to short reflection questions. These questions will help you think about what you learned, what you struggled with, and how you can improve next time. The questions are given in the "Reflection" slide in the Ed assessment.

Running and Submitting

Running and Submitting You can run your program by clicking the "Run" button in Ed. This will compile and execute your code and show you any errors, or the output of your program if it runs correctly. If you believe your output is correct, you can submit your work by clicking the "Mark" button in the Ed lesson. You will see the results of some automated tests along with tentative grades. This grade is not final until you have received feedback from your TA.

You may submit your work as often as you like until the deadline; we will always grade your most recent submission. Note the due date and time carefully—work submitted after the due time will not be accepted.