CSC 322 Systems Programming Fall 2019
Lab Assignment L1: Cipher-machine
Due: Monday, September 23
1 Goal
In the first lab, we will develop a system program (called cipher-machine) which can encrypt
or decrypt a code using C language. It must be an errorless program, in which user repeatedly
executes pre-defined commands and quits when he or she wants to exit. For C beginners, this
project will be a good initiator to learn a new programming language. Students who already
know C language will also have a good opportunity to warm up their programming abilities
and get prepared for the rest of labs.
2 Introduction
A. Basic Commands
The system program provides three basic commands shown in Table 1. The program runs
a related function or exits when a user enters a command as seen in Figure 1. Note that
commands need parameters. Misspelled command should be handled as an exception, and
the program must show an error message. Note that program must be in running and shows
the next prompt.
Table 1. Basic Commands
Command Description
encrypt Encrypt user’s input based on Caesar’s cipher. See the section II-B.
decrypt Decrypt user’s input based on Caesar’s cipher. See the section II-B.
encode Encode user’s input to get a binary code based on ASCII code. See the
section II-C. (extra)
decode Decode user’s binary input to get a character code. See the section II-C.
(extra)
exit Exit the program
The program should run on Linux machine at cs.oswego.edu. Once it is compiled and
executed, it draws user to its own computing environment by showing prompt following the
format: your_loginID $. Figure 1 shows how the prompt looks when the logID is jwlee.
When a command is correctly executed, output will be printed out immediately. The logID
will be printed by using printf function.
jwlee@altair~ > cc lab1-jwlee.c -o lab1
jwlee@altair~ > ./lab1
jwlee $ exot
[Error] Please enter the command correctly!
jwlee $ encrypt(“hello”)
ebiil
jwlee $ exit
2
jwlee@altair~ >
Figure 1. Command Mode
B. Caesar’s Cipher: encrypt/decrypt
Caesar’s cipher is one of cryptography methods, which has a long history, back to Julius
Caesar’s Roman Empire. He used this simple yet efficient method in sending and receiving
private messages with his subordinates and political comrades. The method is based on a
substitution cipher technique in which substitute an alphabet letter to a different alphabet letter
by a certain rule. Look at the list of alphabets in the Figure 2. In this plaintext each
character has a certain positional number, for example “A” has 1, meaning the first character.
In the same manner, “B” has 2, “C” has 3, and so on. To get the ciphertext, all positional
number is shifted right by a proposed number, 3 in the Figure 2. By the shifting rule, “A”
is now in the 4th position, “B” is in the 5th position.
Figure 2. Shifts in Caesar’s cipher method
The shifting rule has issues when it shifts alphabets at the end. See Y and Z. After shifting 3,
Y which was in 25th position should move to 28th position, but it is out of range of alphabet.
Caesar solved it by modular operation, which means the positional number after shifting is
modularized by the size of alphabets. For simplicity, let say A is in 0, B is in 1, and so on.
Then the encryption formula E to get cipher text C from plain text P is below:
C = E(k, P) = (P + k) (mod 26)
In the formula k stands for the number of shifts and k is 3 in our example. Similarly, a cipher
text can be decrypted by the following formula D:
P = D(k, C) = (C - k) (mod 26)
A cipher message can be decrypted by person who knows k. It makes the method secure. For
example, the following sentence is encrypted to a cipher message, which will be sent:
Actual message: SEE ME AFTER CLASS
Sending message: VHH PH DIWHU FODVV
Because you are given k above, you can understand the sending message, VHH PH DIWHU
FODVV and will see me after class. But who don’t know it cannot see me, right?
However, Caesar’s Cipher covers only 26 alphabet letters. Numbers cannot be encrypted. In
this program, thus you extend it to cover characters in ASCII code1. Each ASCII character is
encoded to an 8-bit number (7 bits are used in the traditional code). For example, “A” is 65,
“B” is 66, the number “0” is 48, “1” is 49. Lowercases are also differentiated, for example,
“a” is 97, “b” is 98. Moreover, it covers other special characters such as “!”, “+”, and so on.
Because it encrypts more than 26 characters, it definitely enhances the secure level!
A B C D E F … Y Z
X Y Z A B C … V W
… Y Z
A B …
plaintext
ciphertext
3
In your program, you will encrypt a plaintext to get a ciphertext when k is 3. And you will
decrypt a given ciphertext to get a plaintext. Your program will run as shown in Figure 3.
Note that it must follow the correct syntax below:
encrypt(plaintext)
decrypt(ciphertext)
Any typos in entering the command should be caught and returns an error message. It includes
the format of command.
jwlee $ encrypt(I have a key)
L#kdyh#d#nh|
jwlee $ encrypt(see me at 3)
vhh#ph#dw#6
jwlee $ decrpyt(qr#l#fdq#phhw#dw#<)
no i can meet at 9
jwlee $ encr(see you soon)
[Error] Please enter the command correctly!
jwlee $ decrypt “rndb”
[Error] Please enter the command correctly!
jwlee $
Figure 3. encrypt/decrypt example
After the output, the system must print prompt so that user enters a next command. Are you
ready? JRRG OXFN!!
C. [Extra work] Encoding/Decoding: encode/decode
It is not mandatory but optional, which means those who develop this command will earn
extra credits up to 6 points per command. The commands are executed when you want to
encode a text to a binary code and decode a binary code to a readable text. The encoding and
decoding are commonly used in editing video or audio data. The idea is to convert data (of
image, video, audio, etc.) to a format which can be read and managed by machine. Since the
machine is a passive device which can use two characters - 0 and 1, the format is usually
written in the binary code. There is variation for the format, but you implement a simple
encoder/decoder, which convert a character into its ASCII code’s binary code. You can use
the ASCII code in the last page. See the example of encode and decode commands in Figure
4. The text “key” has three ASCII codes of 107, 101, and 121. The encoder converts them into
a binary number (01101011, 01100101, 01111001) and concatenate them. Note that the
traditional ASCII code has 7 bits code, but you will consider 8-bit code which enables 8 bits
Unicode. Thus, after convert 107 to 1101011, and make it 01101011 by putting 0 in the
beginning.
jwlee $ encode(key)
011010110110010101111001
jwlee $ encode(7-eleven)
0011011100101101011001010110110001100101011101100110010101101110
jwlee $ encod(location)
[Error] Please enter the command correctly!
4
jwlee $ decode “011100”
[Error] Please enter the command correctly!
jwlee $ decode(here)
[Error] Please enter the command correctly!
jwlee $
Figure 4. bin2dec example
The commands have the following syntax:
encode(text)
decode(binary code)
You should check misspelled commands and incorrect syntax. And you should check binary
code input for decode command, since it decodes “binary code” to a text. Look at the last case
of decode(here) in the Error! Reference source not found.. It is incorrect, because “here” is
not a binary code. After the output, the system must print prompt so that user enters a next
command.
Each command is worth 6 points, thus those who develop both commands will get 12 points.
3 Hints in Implementation
A. Reading user input
There are several ways to get your input: scanf, sscanf, gets, fgets, and so on. But
the best way to handle exceptions such as non-numerical inputs and excess of inputs is to get a
string and parse it into required forms. For needs, the good choice is fgets but not limited to
use other functions in this lab. Find full descriptions of the functions using man.
B. Parsing user input
Once user enters a command, the system must parse it to recognize the type of command and
input. Tokenizer enables to parse commands and return the information needed for further
processing. String library provides necessary functions such as strtok. Find full
descriptions of the functions using man.
4 Requirements
A. Developing environment
The program should be implemented in C only. The program in another language will not be
graded. And the program should be executable in CS Linux machine. The program which
cannot be compiled or executed in the CS Linux machine will be considered as incomplete
program and will lose most points.
B. Handling exceptions
The program must detect errors while running. The errors may occur when user violates the
syntax of the command or enters incorrect inputs (characters, more than required inputs, or
see more in the section II). When the program detects any error cases, it should handle
5
properly by giving some error messages to the user, and still be runnable. The program,
which fails to detect errors and to properly handle them, will lose points.
C. Readability of source code
The source code should be easy to read with good indentation and proper amount of
comments.
D. Creating a readme file
The program should be submitted along with a readme file which has information such as
your ID, name, etc. Students who work on the extra work should notify to instructor through
the readme file. It also may provide a special instruction to run this program if exists. The
source file and readme file should be named following the format below. Those who are not
following the naming rule will also be taken off penalty points.
lab1-your_loginID.c
lab1-your_loginID_readme.txt
E. Submitting by due
I have written the code without the extra section (encode & decode).
If that section is needed, Please comment. I shall add the section C(extra) part.
CODE Solution:
#include <stdio.h>
#include <string.h>
//encrypt function with key=3
void encrypt(char message[100])
{
char ch;
int i;
int key=3;
for(i = 0; message[i] != '\0'; ++i)
{
ch = message[i];
//encrypt lowercase alphabets
if(ch >= 'a' && ch <=
'z')
{
ch = ch +
key;
if(ch >
'z')
ch = ch - 'z' + 'a' - 1;
message[i] =
ch;
}
//encrypt uppercase alphabets
else if(ch >= 'A' && ch
<= 'Z')
{
ch = ch +
key;
if(ch >
'Z')
ch = ch - 'Z' + 'A' - 1;
message[i] =
ch;
}
//encrypt any other character
else
{
ch = ch + key;
message[i] = ch;
}
}
printf("Encrypted message: %s", message);
printf("\nEnter next command: ");
}
//decrypt function with key=3
void decrypt(char message[100])
{
char ch;
int i;
int key=3;
for(i = 0; message[i] != '\0'; ++i)
{
ch = message[i];
if(ch >= 'a' && ch <=
'z'){
ch = ch -
key;
if(ch <
'a')
ch = ch + 'z' - 'a' + 1;
message[i] =
ch;
}
else if(ch >= 'A' && ch
<= 'Z'){
ch = ch -
key;
if(ch <
'A')
ch = ch + 'Z' - 'A' + 1;
message[i] =
ch;
}
else
{
ch = ch - key;
message[i] = ch;
}
}
printf("Decrypted message: %s", message);
printf("\nEnter next command: ");
}
int main()
{
//get user input of the commands
printf("\nEnter any one of the below commands in the given format
:");
printf("\n 1. encrypt(plaintext) \n 2. decrypt(ciphertext) \n 3.
encode(text) \n 4.decode(binary) \n 5.exit \n ");
//infinite loop till user exits
do
{
char command[100];
gets(command);
char cmd1[10],ch;
char msg1[100];
int i;
//check for exit command
if (strcmp(command,"exit") == 0)
return 0;
//check the command and send to corresponding function
else
{
//gets the substring in form of 'encrypt()' or 'decrypt()'
//neglect the text given to check the accuracy of the command
format
for(i = 0; i<=7; ++i)
{
cmd1[i]=command[i];
}
i=0;
while(command[i] != '\0')
{
i++;
}
cmd1[8]=command[i-1];
cmd1[9]='\0';
//extracting the text
int k=0;
for(int j=8 ; j<i-1; j++)
{
msg1[k++]=command[j];
}
//check the command
if(strcmp(cmd1,"encrypt()") == 0)
encrypt(msg1);
else if(strcmp(cmd1,"decrypt()") == 0)
decrypt(msg1);
else
printf("Incorrect command...Please enter command
correctly : ");
}
}while(1);
}
CODE Screenshot:
CODE OUTPUT Screenshot:
Get Answers For Free
Most questions answered within 1 hours.