PA 1: Enigma Machine
Due date: January 28 23:59
Table of contents
- Learning Goals
- Getting Help
- Before we Begin..
- Introduction
- Encryption and Decryption
- Getting Started
- Program Specifications
- Skeleton Code Description
- Tests
- Submission Instructions
- Submission Instructions
- Grading and Point Distribution
- CSE 29 Reflection Survey 1
Learning Goals
In this assignment, we will–
- Learn how to write a C program that follows the given specifications,
- Learn how functions improve code by making it modular and task oriented,
- Practice calling functions from different functions,
- Practice passing arguments to functions,
- Practice returning values from functions,
- Develop code using one-dimensional and two-dimensional arrays,
- Learn to write code that allocates and frees memory for arrays dynamically on the heap
Getting Help
You are always welcome to come to either instructor or TA office hours. Both of which are listed on the course website. In office hours, however, conceptual questions will be prioritized.
If you need help while working on this PA, make sure to attend tutor hours. Tutor hours policy can be found in the syllabus.
You can also post questions on Piazza or collaborate with your peers 👀
Collaboration guide
Before we Begin..
Read the whole thing!
The Importance of Reading
One of the best ways to suffer in CSE 29 programming assignments is not paying enough attention to the assignment specifications. Yes, these documents can be very long, but they are long because they contain a lot of useful information that you will need to successfully complete the tasks.
Reading is one of the most important skills to have as a software engineer. Not only should you become comfortable with reading long specifications, you also need to be able to read and understand documentations, which you will have plenty of opportunity to practice throughout this quarter.
Do not shy away from reading! Read this whole document thoroughly!
Incremental Development and Testing
Another good way to suffer in CSE 29 is to not follow the principles of incremental development and testing.
A very critical skill we hope you will obtain after CSE 29 is that of problem decomposition: how to break down a complicated problem into smaller parts? In some ways, we help you with that in CSE 29 by providing you with structured skeleton code for each assignment, so that you can see what the smaller tasks are for each PA. But with that, you still need to take an incremental approach to programming.
Put simply, don’t write too much code at once without testing. If you have written a few lines of code, think about how you can test it to make sure everything is working as intended before moving on to the next part.
If you don’t, bugs will inevitably pile up and bury you underneath.
You should never find yourself compiling and running your code for the first time only after thinking you have finished coding the entire assignment.
I speak from experience.
Follow our advice!
Please?
Introduction
In this project, you will follow the program specifications given below, to write a C program which implements a simplified version of an encrypting and decrypting machine called Enigma.
The Enigma was invented by German engineer Arthur Scherbius and was used during World War II. This machine accepts the message that needs to be encrypted, uses some predefined rotors to encrypt the message and outputs the result. Also, it can accept encrypted messages and decrypt them.
In this project you will implement both of these functionalities.
The Enigma you implement in this PA might seem simple by the end but the Enigma machine was not. It was used by the German military to encrypt and decrypt messages during World War II. The Enigma machine was considered unbreakable until the British mathematician Alan Turing(yes, that turing) and his team at Bletchley Park cracked the code. Learn more here.
Encryption and Decryption
Encryption in Enigma
The Enigma machine uses so-called rotors to encrypt messages. In the starter code for enigma.c
, there is an array of strings called enigma_rotors
that stores 9 rotors. For our project, the rotor at position 0 is an identity rotor. It is basically a string with original English alphabets in the normal alphabetical order.
Rotor 0 is given to help you better see how the encryption and decryption processes occur. You cannot really use this rotor to encrypt messages since the original message will not change.
Rotors at positions 1 - 8 of the array enigma_rotors
are strings with the letters of the alphabet appearing in various orders. For example, the rotors 0 to 3 are shown below.
Rotor 0 - ABCDEFGHIJKLMNOPQRSTUVWXYZ
Rotor 1 - EKMFLGDQVZNTOWYHXUSPAIBRCJ
Rotor 2 - AJDKSIRUXBLHWTMCQGZNPYFVOE
Rotor 3 - BDFHJLCPRTXVZNYEIWGAKMUSQO
Encryption: One Rotor
The encryption process can involve one or multiple rotors.
Let’s look at an example:
Message to be encrypted: JAVA
Rotors to use: 1
Number of rotations: 0
Encrypted message: ZEIE
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
E K M F L G D Q V Z N T O W Y H X U S P A I B R C J -> rotor 1
The position of J
in the original alphabet is 9
. Therefore, the Enigma finds the letter at position 9
on rotor 1
which is Z
. Similarly, the position of A
in the original alphabet is 0
. So, the Enigma finds the letter at position 0
on rotor 1
which is E
, etc. This is how the message JAVA
has been encrypted to ZEIE
using rotor 1
(without performing any rotations …oh boy).
Encryption: Multiple Rotors
Let’s look at another example but this time with multiple rotors.
Encryption using multiple rotors is done in the same as with a single rotor, however, there will be multiple rounds of encryption. …huh?
What this means is that the output of the first round of encryption is fed as the input to the second round of encryption, and so on.
Message to be encrypted: JAVA
Rotors to use: 1 2 4
Number of rotations: 0
Encrypted message: PTMT
The rotors 1, 2, and 4 that are used for encryption are shown below:
====================================================
ROTORS 1, 2, 4
====================================================
E K M F L G D Q V Z N T O W Y H X U S P A I B R C J -> rotor 1
A J D K S I R U X B L H W T M C Q G Z N P Y F V O E -> rotor 2
E S O V P Z J A Y Q U I R H X L N F T G K D C M W B -> rotor 4
----------------------------------------------------
Round 1:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
E K M F L G D Q V Z N T O W Y H X U S P A I B R C J -> rotor 1
(result is ZEIE after using rotor 1 for encryption)
Round 2:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
A J D K S I R U X B L H W T M C Q G Z N P Y F V O E -> rotor 2
(result is ESXS after using rotor 2 for encryption)
Round 3:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
E S O V P Z J A Y Q U I R H X L N F T G K D C M W B -> rotor 4
(result is PTMT after using rotor 4 for encryption)
The first round of encryption as we saw previously, is done using the first rotor and the result is ZEIE
in our example. This result is then passed on to rotor 2
, the output of which is ESXS
. This is then passed on to rotor 4
which gives us the final encrypted message PTMT
.
See why this took so long to crack?
Decryption in Enigma
The decryption process is the reverse of the encryption process. To decrypt the message PTMT
that we encrypted in the previous example back to JAVA
, the order of the rotors should be reversed. Since we used rotors 1, 2, and 4, in that order, for encryption, we should use rotors 4, 2, and then 1 for decryption.
Message to be decrypted: PTMT
Rotors to use: 4 2 1
Number of rotations: 0
Decrypted message: JAVA
First, we start with rotor 4
and find the letters PTMT
. We then find the letters in these positions on the identity rotor, i.e. rotor 0
. This gives us ESXS
.
We then pass ESXS
to rotor 2
and decrypt it to ZEIE
. Finally, we pass ZEIE
to rotor 1
and decrypt it to JAVA
.
Rotating the rotors
If by this point you were wondering why the rotors were called rotors, well you’re about to find out.
While performing encryption or decryption of the message, we enter some non-negative integer number of rotations. Number of rotations is simply the number of times you want to move the rotor values to the right (each row).
For example, for rotor 1 if you want to perform rotation = 3
, then
Rotor 1: E K M F L G D Q V Z N T O W Y H X U S P A I B R C J
Rotated rotor 1: R C J E K M F L G D Q V Z N T O W Y H X U S P A I B
Similarly, the effects of rotating rotors 1, 2 and 4 three times are shown below:
====================================================
ROTORS 1, 2, 4 BEFORE ROTATION
====================================================
E K M F L G D Q V Z N T O W Y H X U S P A I B R C J -> rotor 1
A J D K S I R U X B L H W T M C Q G Z N P Y F V O E -> rotor 2
E S O V P Z J A Y Q U I R H X L N F T G K D C M W B -> rotor 4
----------------------------------------------------
====================================================
ROTORS 1, 2, 4 AFTER ROTATING THEM 3 TIMES
====================================================
R C J E K M F L G D Q V Z N T O W Y H X U S P A I B -> rotor 1
V O E A J D K S I R U X B L H W T M C Q G Z N P Y F -> rotor 2
M W B E S O V P Z J A Y Q U I R H X L N F T G K D C -> rotor 4
----------------------------------------------------
After rotating the rotors, encryption or decryption can be performed as usual.
If you rotate the rotors n
times during encryption, you should rotate them n
times during decryption as well to get the correct output. Keep in mind though, that the order of the rotors should be reversed during decryption.
For instance,
Message to be encrypted: JAVA
Rotors to use: 1 2 4
Number of rotations: 3
Encrypted message: MQBQ
Round 1:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
R C J E K M F L G D Q V Z N T O W Y H X U S P A I B -> rotor 1 (rotated)
(result is DRSR after using rotor 1 (rotated 3 times) for encryption)
Round 2:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
V O E A J D K S I R U X B L H W T M C Q G Z N P Y F -> rotor 2 (rotated)
(result is AMCM after using rotor 2 (rotated 3 times) for encryption)
Round 3:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -> rotor 0
M W B E S O V P Z J A Y Q U I R H X L N F T G K D C -> rotor 4 (rotated)
(result is MQBQ after using rotor 4 (rotated 3 times) for encryption)
Notice how the output is MQBQ
and not PTMT
as we saw in the previous example. This is because we rotated the rotors 3 times before encryption.
Now to decrypt,
Message to be decrypted: MQBQ
Rotors to use: 4 2 1
Number of rotations: 3
Decrypted message: JAVA
Phew that was a lot of text.
Now for some more 🫠Getting Started
Now that we have a decent understanding of how the Enigma machine works, it’s time to make our own.
All of our programming assignments will be hosted on GitHub Classoom. Use the following link to accept the GitHub Classroom assignment.
Click here to accept this GitHub Classroom assignment. (Right click to open in new tab)
Once the assignment is accepted, you will see a repository generated for you with the started code for this assignment. Click the link to go to the repository.
Repo… what? Many of you may not have dealt with Git or GitHub before. Don’t worry, you will learn about it in the upcoming labs. For now, simply follow our instructions.
Once you are in the repository, click on the green Code
button and click on Download ZIP
. This will download the repository to your local machine. Now, extract the contents of the downloaded zip file using your favorite archive manager.
The extracted folder will contain the following files:
enigma.c
README.md
The enigma.c
file is where you will write your code. The README.md
file, has the link to this website for your reference.
Can I get started now? Y- No. Read the whole thing.
The enigma.c
File
We will write all the code in this class on the ieng6
server. So, we need to get this file there. How?
We will first move the file into a sensible location on our local machine.
MacOS & Linux
Now, if you are on macOS or Linux, you should be able to move the enigma.c
file into your home directory. To open your home directory on macOS, follow these steps:
- Open Finder.
- Use the shortcut Command + Shift + H to quickly navigate to your home directory.
- Place the file.
Windows (WSL)
If you are on Windows, and on WSL, then it is slightly more tricky to move the file, since WSL is actually running a separate file system on top of your Windows file system. But the good news is you can still open the WSL file system in Windows.
Run the following commands in your WSL terminal. This will open up familiar Windows Explorer window with the WSL file system. Simply drag and drop the enigma.c
file into this window. You should now be able to verify this by running the ls
command.
$ cd ~/
$ explorer.exe .
You can run regular windows programs from the terminal too! How exciting.
Moving the file to ieng6
Now we will get this file onto the ieng6
server. If you don’t remember how to log onto it, now would be a good time to go through the instructions from Lab 1 again.
Once you are logged into the server, run the following commands-
$ mkdir ~/cse29/pa1
$ cd ~/cse29/pa1
The first command (mkdir) creates a directory called pa1 in your cse29. The next one (cd) moves you into this directory.
We will use the scp
command to copy the enigma.c
file to the ieng6
server.
The SCP command
scp
is an important part of the ssh toolchain. It is used for copying files. It is very similar to cp
in syntax and functionality except you can specify a file on a remote machine as a copy source and/or destination.
Remember that our ssh connection consists of both ssh clients and ssh servers. In our case, your personal device – or more specifically, the ssh program on your personal device – acts as the ssh client. The ieng6
server acts as the ssh server.
The scp
command is a client-side command, which means it should always be run from the client side. So, if you are currently logged into ieng6
, you can either:
- log out by using the
exit
command, or - open a second terminal on your devices without connecting to
ieng6
. (If you are on Windows, this means opening up another WSL terminal.)
Having done this, we run the scp
command from the client side:
$ scp source-file destination-file
In this case, source-file
is the engima.c
file on the your computer, destination-file
is where we want it to be on the server side, i.e., ieng6
.
To specify a remote file, we use a combination of the remote server name and the file path on that remote server, joined together by a colon (:
).
For example, say I want to copy my local enigma.c
file to my remote server harsha@ieng6.ucsd.edu
in the directory ~/cse29/pa1
. From my local machine(not from the ieng server), I would run the following command:
$ scp /home/harsha/enigma.c harsha@ieng6.ucsd.edu:~/cse29/pa1
So, in your case, the command syntax will be as follows:
$scp your/file/path/to/enigma.c aname@ieng6.ucsd.edu:~/cse29/pa1
When you run this command, you will be prompted to enter your password for the ieng6 server, just like with ssh
.
The ~
symbol is a shortcut for the home directory of the user.
You should now have the file on your ieng6
server. You can verify this by running the ls
command in the pa1
directory(cd
into it).
For students using WSL: When you run the ls command to check for the enigma.c
file, you may notice an additional file named enigma.c:Zone.Identifier
. This file is automatically created to store metadata. You can remove it by using the command rm enigma.c:Zone.Identifier
.
We will use this command but in reverse later when we want to copy the file and submit it to Gradescope. Given all this information, can you guess how?
Program Specifications
Okay, now that we have the enigma.c
file on the ieng6
server, you can use cat
command to look at the contents of the file. Familiarize yourself with the skeleton code to understand the structure and where to implement your functions.
- YOU SHOULD NOT:
- Modify the parameters of any function in
enigma.c
, - Modify the return type of any function in
enigma.c
, - Include any other libraries apart from the ones provided. You can add utility functions if you need them.
- Modify the parameters of any function in
- You will have to make changes to the
enigma.c
file and fill out all the function definitions. You are recommended to use vim to edit the files. - The command line arguments: mode (encryption or decryption), string to be encrypted or decrypted, number of rotors, rotor indices string and number of rotations must be read in the below format –
./enigma e "JAVA" 3 "1 2 4" 0
where,e
is the mode (e for encryption, d for decryption),"JAVA"
is the string to be encrypted or decrypted; can contain uppercase and lowercase letters, numbers, and special characters,3
is the number of rotors to use,"1 2 4"
is the rotor indices string; space-separated indices of the rotors to use; each index belongs to the range [1, 8],0
is the number of rotations to perform on the rotors before encryption or decryption; this can be any non-negative integer.
- Correct format of the input is guaranteed. This means that we will not test your code against invalid input, and you can assume that all test cases follow the correct format specified in the previous bullet point.
Handling Command-Line Arguments
In the past, you may have used String args[]
in Java to handle command-line arguments. Similarly in C, argc
(argument count) and argv
(argument vector) are used to handle command-line arguments passed to a program:
argc: Represents the number of arguments passed, including the program name itself.
argv: An array of strings (character pointers) that hold the arguments. argv is a pointer to pointers. The first element, argv[0]
, is the program’s name, and subsequent elements are the additional arguments.
Here’s a simple example that prints all command-line arguments:
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Number of arguments: %d\n", argc);
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
return 0;
}
If you save the above snippet as args.c and after compiling the program, run it like this:
./args hello "1 4 5" 123
The output will be:
Number of arguments: 4
argv[0]: ./args
argv[1]: hello
argv[2]: 1 4 5
argv[3]: 123
Notice how argc
is 4 (program name + 3 arguments) and argv[0]
contains the program name.
Skeleton Code Description
The first step of the program is to extract all the command-line arguments inside the main() function and store them in variables (using appropriate data types). Once this is completed, you can start implementing and calling the functions listed below from within your main() function.
parse_rotor_indices()
Function
int* parse_rotor_indices(char* rotor_ind_str, int num);
The first step is to pass the rotor indices string and the number of rotors to the parse_rotor_indices
function(remember C arrays don’t know their own size).
This function should parse the rotor indices string and return an array of integers. The array should contain the indices of the rotors to be used for encryption or decryption.
For example, if the input is "1 3 4"
, then the function should return an array of integers {1, 3, 4}
.
set_up_rotors()
Function
int** set_up_rotors(int* rotors, int num);
Now, you need to pass the array of integers returned by the parse_rotor_indices()
function and the number of rotors to the set_up_rotors()
function.
This function creates and returns the 2D array rotor_config
which contains the number of rows as specified in num
and the number of columns equal to the rotor length.
For instance, if the input is {1, 3, 4}
, then the function should return a 2D array of 3 rows and the values of each row will be the rotor configurations represented by the number of the alphabet in each position i.e. A would be 0, B would be 1, and so on-
Rotor 1 contains: EKMFLGDQVZNTOWYHXUSPAIBRCJ
Representation: [4 10 12 5 11 6 3 16 21 25 13 19 14 22 24 7 23 20 18 15 0 8 1 17 2 9]
E -> 4
K -> 10 ...
So, for the configuration {1, 3, 4}
, the 2D array should look like this-
[4 10 12 5 11 6 3 16 21 25 13 19 14 22 24 7 23 20 18 15 0 8 1 17 2 9]
[1 3 5 7 9 11 2 15 17 19 23 21 25 13 24 4 8 22 6 0 10 12 20 18 16 14]
[4 18 14 21 15 25 9 0 24 16 20 8 17 7 23 11 13 5 19 6 10 3 2 12 22 1]
rotate_rotors()
Function
void rotate_rotors(int** rotor_config, int rotations, int num_rotors);
Now that we have the rotors set up, we’re going to spin them right round.
This function accepts the int rotations
and the 2D array rotor_config
, and num_rotors
which is the number of rotors. The function should rotate each rotor in the array to the right by rotations
positions.
For instance-
rotor_config:
[4 10 12 5 11 6 3 16 21 25 13 19 14 22 24 7 23 20 18 15 0 8 1 17 2 9]
[1 3 5 7 9 11 2 15 17 19 23 21 25 13 24 4 8 22 6 0 10 12 20 18 16 14]
[4 18 14 21 15 25 9 0 24 16 20 8 17 7 23 11 13 5 19 6 10 3 2 12 22 1]
rotations: 3; num_rotors: 3
The function should change rotor_config like so:
[17 2 9 4 10 12 5 11 6 3 16 21 25 13 19 14 22 24 7 23 20 18 15 0 8 1]
[18 16 14 1 3 5 7 9 11 2 15 17 19 23 21 25 13 24 4 8 22 6 0 10 12 20]
[12 22 1 4 18 14 21 15 25 9 0 24 16 20 8 17 7 23 11 13 5 19 6 10 3 2]
Now, what happens when the number of rotations exceed 25 (the maximum index in a 26-letter alphabet)?
In such cases, the rotations should “wrap around” using modulo arithmetic. Example scenarios:
If rotations = 26, this is equivalent to rotating by 0 positions (complete cycle back to start)
If rotations = 27, this is equivalent to rotating by 1 position (27 % 26 = 1)
If rotations = 52, this is equivalent to rotating by 0 positions (52 % 26 = 0)
If rotations = 29, this is equivalent to rotating by 3 positions (29 % 26 = 3)
For instance -
rotor_config:
[4 10 12 5 11 6 3 16 21 25 13 19 14 22 24 7 23 20 18 15 0 8 1 17 2 9]
[1 3 5 7 9 11 2 15 17 19 23 21 25 13 24 4 8 22 6 0 10 12 20 18 16 14]
[4 18 14 21 15 25 9 0 24 16 20 8 17 7 23 11 13 5 19 6 10 3 2 12 22 1]
rotations: 29; num_rotors: 3
The function should change rotor_config like so:
[17 2 9 4 10 12 5 11 6 3 16 21 25 13 19 14 22 24 7 23 20 18 15 0 8 1]
[18 16 14 1 3 5 7 9 11 2 15 17 19 23 21 25 13 24 4 8 22 6 0 10 12 20]
[12 22 1 4 18 14 21 15 25 9 0 24 16 20 8 17 7 23 11 13 5 19 6 10 3 2]
Since 29 % 26 = 3, this example shows the rotors being rotated 3 positions to the right, which helps demonstrate the wraparound behavior.
encrypt()
and decrypt()
Functions
char* encrypt(char *message, int** rotor_config, int num_rotors);
char* decrypt(char *message, int** rotor_config, int num_rotors);
The star(s) of the show. These functions will perform the encryption and decryption of the message.
These functions both accept a string message
to be encrypted or decrypted, the 2D array rotor_config
, and num_rotors
which is the number of rotors.
The keen-eyed among you will notice that the rotors only have uppercase letters. So, these functions should change the string to all uppercase characters before encryption or decryption. For instance-
"all is well" --> "ALL IS WELL"
The functions will both return an array of characters. The encrypt()
function should return the encrypted message, and the decrypt()
function should return the decrypted message. The strings returned will always be UPPERCASE.
Input messages can contain whitespaces, numbers, and special characters in addition to uppercase(A-Z)
and lowercase(a-z)
letters, but only the letters will be encrypted or decrypted and the rest will remain the same.
Tests
Programs must be tested comprehensively to ensure that you have more than just hopes and prayers to rely on when you submit your code.
Here are the test cases that we will run on your code(you should too):
If you plan to rely on the autograder to test your code, keep in mind that you will only be able to see your program’s performance against the public test cases. The performance of your code on the hidden test cases will remain unavailable until after the deadline. Therefore, make sure to thoroughly test your code against the hidden test cases as well.
Only 1 rotor without rotation
Public cases
$ ./enigma e "JAVA" 1 "5" 0
Encrypted message: VUNU
$ ./enigma d "VUNU" 1 "5" 0
Decrypted message: JAVA
Hidden cases
Message to be encrypted: enigma
Rotors to use: 1
Number of rotations: 0
Encrypted message: LWVDOE
Message to be decrypted: lwvdoe
Rotors to use: 1
Number of rotations: 0
Decrypted message: ENIGMA
Message to be encrypted: There are 2 hard things in CoMpUtEr ScIeNcE: cache invalidation, naming things, and off-by-one errors.
Rotors to use: 3
Number of rotations: 0
Encrypted message: APJWJ BWJ 2 PBWH APRNCG RN FYZEKAJW GFRJNFJ: FBFPJ RNMBVRHBARYN, NBZRNC APRNCG, BNH YLL-DQ-YNJ JWWYWG.
Message to be decrypted: Apjwj bwj 2 pbwh aprncg rn FyZeKaJw GfRjNfJ: fbfpj rnmbvrhbaryn, nbzrnc aprncg, bnh yll-dq-ynj jwwywg.
Rotors to use: 3
Number of rotations: 0
Decrypted message: THERE ARE 2 HARD THINGS IN COMPUTER SCIENCE: CACHE INVALIDATION, NAMING THINGS, AND OFF-BY-ONE ERRORS.
Message to be encrypted: C_is#gr8te_&-fun+15784
Rotors to use: 7
Number of rotations: 0
Encrypted message: J_MV#CI8LG_&-RPO+15784
Message to be decrypted: J_mv#ci8lg_&-rpo+15784
Rotors to use: 7
Number of rotations: 0
Decrypted message: C_IS#GR8TE_&-FUN+15784
Multiple rotors without rotation
Public cases
$ ./enigma e "JAVA" 2 "5 4" 0
Encrypted message: DKHK
$ ./enigma d "DKHK" 2 "4 5" 0
Decrypted message: JAVA
Hidden cases
Message to be encrypted: enigma
Rotors to use: 1 3 4
Number of rotations: 0
Encrypted message: DKRAWQ
Message to be decrypted: dkrawq
Rotors to use: 4 3 1
Number of rotations: 0
Decrypted message: ENIGMA
Message to be encrypted: There are 2 hard things in CoMpUtEr ScIeNcE: cache invalidation, naming things, and off-by-one errors.
Rotors to use: 8 2 6
Number of rotations: 0
Encrypted message: UNHIH YIH 2 NYIX UNVBLA VB DOGMSUHI ADVHBDH: DYDNH VBCYWVXYUVOB, BYGVBL UNVBLA, YBX OFF-EK-OBH HIIOIA.
Message to be decrypted: Unhih yih 2 nyix unvbla vb DoGmSuHi AdVhBdH: dydnh vbcywvxyuvob, bygvbl unvbla, ybx off-ek-obh hiioia.
Rotors to use: 6 2 8
Number of rotations: 0
Decrypted message: THERE ARE 2 HARD THINGS IN COMPUTER SCIENCE: CACHE INVALIDATION, NAMING THINGS, AND OFF-BY-ONE ERRORS.
Message to be encrypted: C_is#gr8te_&-fun+15784
Rotors to use: 3 1 5
Number of rotations: 0
Encrypted message: X_OB#IK8ES_&-TYD+15784
Message to be decrypted: X_ob#ik8es_&-tyd+15784
Rotors to use: 5 1 3
Number of rotations: 0
Decrypted message: C_IS#GR8TE_&-FUN+15784
Multiple rotors with rotation
Public cases
$ ./enigma e "JAVA" 2 "5 4" 3
Encrypted message: KXQX
$ ./enigma d "KXQX" 2 "4 5" 3
Decrypted message: JAVA
Hidden cases
Message to be encrypted: enigma
Rotors to use: 1 3 4
Number of rotations: 43
Encrypted message: KJNFZE
Message to be decrypted: kjnfze
Rotors to use: 4 3 1
Number of rotations: 43
Decrypted message: ENIGMA
Message to be encrypted: There are 2 hard things in CoMpUtEr ScIeNcE: cache invalidation, naming things, and off-by-one errors.
Rotors to use: 8 2 6
Number of rotations: 17
Encrypted message: HBULU XLU 2 BXLC HBFSQI FS AVREWHUL IAFUSAU: AXABU FSNXZFCXHFVS, SXRFSQ HBFSQI, XSC VMM-YO-VSU ULLVLI.
Message to be decrypted: Hbulu xlu 2 bxlc hbfsqi fs AvReWhUl IaFuSaU: axabu fsnxzfcxhfvs, sxrfsq hbfsqi, xsc vmm-yo-vsu ullvli.
Rotors to use: 6 2 8
Number of rotations: 17
Decrypted message: THERE ARE 2 HARD THINGS IN COMPUTER SCIENCE: CACHE INVALIDATION, NAMING THINGS, AND OFF-BY-ONE ERRORS.
Message to be encrypted: C_is#gr8te_&-fun+15784
Rotors to use: 3 1 5
Number of rotations: 124
Encrypted message: R_CW#IJ8XZ_&-HDV+15784
Message to be decrypted: R_cw#ij8xz_&-hdv+15784
Rotors to use: 5 1 3
Number of rotations: 124
Decrypted message: C_IS#GR8TE_&-FUN+15784
Submission Instructions
For this PA, you will manually download the file from the ieng6 server and upload it to Gradescope for submission. Don’t worry, we will guide you through the process.
Downloading the enigma.c
file
To download the file you worked on, we’ll need to know its path, which means “where it is” in the file system.
For instance, you should have been working in the pa1
directory that you created earlier. To get the path of this directory, use the pwd
command-
$ pwd
/home/linux/ieng6/oce/73/skavuri/cse29/pa1
This example shows what the output might look like. Run the pwd command on your system and copy the output, as it will provide your specific file path. Use Ctrl + Shift + C
(on Linux) or Cmd + C
(on macOS) to copy the path, or write it down manually if copying is not an option.
Ctrl + C
is used to copy text but it also stops any program that is currently running in the terminal. This is useful if you ever get into an infinite loop or if you want to stop a program that is running. Make sure you don’t use it to copy text when you are running a program.
Now, recall the scp
command from earlier. If what follows makes no sense go back and read the section on scp
again.
We will run the scp
command in reverse to copy the file from the ieng6 server to our local machine. We know that scp
uses the following syntax:
$ scp source-file destination-file
So, we need to specify the source file as the enigma.c
file on the ieng6 server and the destination as our local machine.
Make sure you are running the scp
command from your local machine and not from the ieng6 server.
The command will look something like this:
$ scp aname@ieng6.ucsd.edu:~/cse29/pa1/enigma.c ~/
Here, aname
is your account name. This command will copy the enigma.c
file from the pa1
directory on the ieng6 server to your home directory on your local machine.
Now that you can access your file(if you don’t know how, go back and read the “Getting Started” section), go ahead and make the Gradescope submission.
Submission Instructions
Gradescope
Go to the Gradescope submission page and submit your C file.
Grading and Point Distribution
Your code will be evaluated against 24 test cases (6 public and 18 hidden) with each test case worth 1 point, contributing a total of 24 points.
Additionally, completing the CSE 29 Reflection Survey 1 (explained below) will earn you 1 point.
Overall, the total points for this assignment are 25.
CSE 29 Reflection Survey 1
The last, but equally important part of the assignment is the CSE 29 Reflection Survey 1. Please spend a few minutes reflecting on your experience in this course and give thoughtful and truthful answers, to the best of your ability.
This survey (and others that follow) is not anonymous because (1) you will receive credit for completing this survey and (2) the teaching staff would like to be able to reach out to help students who might need extra support.
Link to the survey - CSE 29 Reflection Survey 1