In: Computer Science
1 Introduction A cipher is an algorithm which encrypts a message into cipher text so that it can be safely transmitted without an eavesdropper being able to (easily) read it. For the purposes of this assignment the message and ciphertext will be stored as strings of ASCII characters. Cipher algorithms always perform two tasks: encryption and decryption. The encryption process takes a “message” and “key” as inputs and produces cipher text. The decryption process performs the reverse: it turns cipher text and the key back into the original message. The exact details of how the key and message are processed to produce the cipher text vary between algorithms. However, the general principle is that algorithms employ a mathematical function which is “easy” to calculate with the key but “difficult” to invert without it. A rigorous discussion of modern cryptographic techniques can be found in the excellent (but highly mathematical) text, An Introduction to Mathematical Cryptography (available in the Auchmuty library). This assignment will cover the substitution cipher. Your task is to write a C program which performs encryption and decryption of a message using the substitution cipher algorithm.
1.1 Substitution Cipher A substitution cipher encrypts a text message by replacing each of the 26 message letters with a different letter. Example with a substitution chosen from the qwerty keyboard layout: Message letter: ABCDEFGHIJKLMNOPQRSTUVWXYZ Cipher text letter: QWERTYUIOPASDFGHJKLZXCVBNM A message is encrypted by substituting each letter in the top row with the one below it. So every A in the message would be replaced with a Q, every B with a W, etc. For example Message: PLEASE GET MILK AT THE SHOPS Cipher text : HSTQLT UTZ DOSA QZ ZIT LIGHL There is no neat algebraic method to write the encryption function. It is effectively a “look-up-table” where each letter, xn, becomes a different letter, yn based on a fixed substitution rule.
2 Programming Task Write a C program which performs encryption and decryption using the substitution cipher algorithm. Your program must be fully automated (ie: it does not take any interactive user input) and either encrypt or decrypt depending on the files which exist in the program’s directory. If message.txt exists your program should read that file, encrypt the contents, and write the output to ciphertext.txt. If ciphertext.txt exists your program should decrypt the contents and write the output to message.txt. If both files exist your program should default to encrypting message.txt. If neither message.txt or ciphertext.txt exist your program should print an error and exit. The key is to be read from key.txt. This file should contain all 26 letters of the alphabet in UPPER CASE and listed in a random order. Your program should print an appropriate error and exit if any of the following conditions are met: • key.txt does not exist • The key contains repeated letters • The key does not contain every letter • The key contains characters which aren’t letters (eg: numbers, spaces, etc) This tasks requires you to check the return value of fopen() when attempting to open files. If a file does not exist then fopen() will return NULL. 2.0.1 Message Specification Your program should be able to read both UPPER and lower-case letters but the output should be in UPPER CASE only. In other words, your program needs to convert all letters in the input to upper case before they are processed. Any character which is not a letter should be copied from input to output without modification. All input and output data is to be encoded with the ASCII standard. ASCII encoding defines that upper and lower case letters be stored as the following 8-bit integers: A 65 a 97 B 66 b 98 C 67 c 100 ... ... Y 89 y 121 Z 90 z 122 If an input byte is outside of the ranges [65, 90] and [97, 122] then it can be copied to the output without modification. If an input byte is in the lower case range, [97, 122], then you should subtract 32 from its value to make it an upper case letter prior to encryption.
2.0.2 Function Specifications Your program must contain and use the following functions: void encrypt(char *ciphertext, char *message, char *key); void decrypt(char *ciphertext, char *message, char *key); This implies that your program must read the entire input file and key into different strings and then pass these strings as arguments to the above functions. The encrypt() function should read from message and write to ciphertext and, likewise, decrypt() should read from ciphertext and write to message. In order to do this note the following: • C allows you to declare an array with a length given as a variable, eg: 1 int len = 128; 2 char str[len]; • The length of a file can be found by opening it, using fseek() with the SEEK END argument, and then using ftell() to find the current value of the position indicator. You can then use fseek() or rewind() to start reading from the beginning of the file. See the fseek() documentation for details.
Please find the answer attached below. I have also added COMMENTS in the code for better understanding of the answer.THANK YOU.
#include<stdio.h>
#include <stdlib.h>
/* NOTE : I HAVE ADDED A FOR LOOP AFTER THE CLOSING OF MESSAGE.TXT TO CONVERT ALL ALPHABETS TO UPPERCASE
ANS I HAVE ALSO ADDED THE CODE FOR PERFORMING ENCRYPTION USING KEY FILE */
int main()
{
char message[128]; //message character array to store the message string
char cipher[128]; //cipher character array to store the cipher string
char key[128]; // array to store the key string
int i;
FILE *fp_message; //pointer to the message.txt file
FILE *fp_cipher; //pointer to the cipher.txt file
FILE *fp_key; //pointer to the key.txt file
fp_message = fopen ("message.txt", "r"); //opening the message.txt
if (fp == NULL) //if it doesn't open show appropriate messages.
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
//Reading the contents of file message.txt into array message[]
//and printing the contents of the file message.txt
while(fgetc(fp)) != EOF)
{
fscanf(fp_message, "%s,", &message[i] );
printf("%c", ch);
}
fclose(fp_message); //close the message.txt file
/* This for loop below converts the lowercase to uppercase without
the use of <ctype.h> library. */
for (i=0 ; message[i]!='\0';i++)
{
if ( message[i] >= 'a' && message[i] <= 'z' )
{
message[i]= message[i]- 32;
}
}
// now the message[] array will have all uppercase values.
fp_key = fopen ("key.txt", "r"); //opening the key.txt
if (fp_key == NULL) //if it doesn't open show appropriate messages.
{
perror("Error while opening the file key.txt\n");
exit(EXIT_FAILURE);
}
//Reading the contents of file key.txt
while(fgetc(fp)) != EOF)
{
fscanf(fp_key, "%s,", &key[i] );
length = ftell(fp_key); // Cursor position is now at the end of file
/* we can use fseek(fp_key, 0, SEEK_END); also to move the
cursor to the end of the file */
rewind (fp_key); // It will move cursor position to the beginning
}
fclose(fp_key); //closing the file key.txt
//performing the encryption
for(i=0;message[i]!='\0';i++)
{
message[i]=message[i]+key[i];
cipher[i]=message[i]; //storing the cipertext in the cipher array.
}
fp_cipher = fopen ("cipher.txt","w"); //opening the file cipher.txt
if (fp_cipher == NULL) //if it doesn't open show appropriate messages.
{
perror("Error while opening the file cipher.txt\n");
exit(EXIT_FAILURE);
}
fputs(cipher,fp_cipher); //writing the content of cipher to cipher.txt file
fclose (fp_cipher); //close the file using file pointer.
}
/* ------ The following code is to explain how key can be used for encryption-----------
char monocipher_encr(char); //this is function prototype for encryption
char monocipher_decr(char); ////this is function prototype for decryption
//SUPPOSE THE KEY.TXT CONTAINS THE FOLLOWING DATA CHAR ALPHA AND CHAR DEALPHA AS GIVEN BELOW
char alpha[27][3]={
{'a','n'}, {'b','k'}, {'c','v'}, {'d','q'}, {'e','f'}, {'f','i'}, {'g','b'}, {'h','j'}, {'i','w'}, {'j','p'}, {'k','e'}, {'l','s'}, {'m','c'}, {'n','x'}, {'o','h'}, {'p','t'}, {'q','m'}, {'r','y'}, {'s','a'}, {'t','u'}, {'u','o'}, {'v','l'}, {'w','r'}, {'x','g'}, {'y','z'}, {'z','d'}
};
char dealpha[27][3]={{'n','a'}, {'k','b'}, {'v','c'}, {'q','d'}, {'f','e'}, {'i','f'}, {'b','g'}, {'j','h'}, {'w','i'}, {'p','j'}, {'k','e'}, {'s','l'}, {'c','m'}, {'x','n'}, {'h','o'}, {'t','p'}, {'m','q'}, {'y','r'}, {'a','s'}, {'u','t'}, {'o','u'}, {'l','v'}, {'r','w'}, {'g','x'}, {'z','y'}, {'d','z'}
};
// NOW CONSIDER THE FOLLOWING CODE --->
char message[200]; //suppose the message which we stored in the program above is this message array
char a ; // temporary character to store a char value
char b;
void encryption(){ // THIS FUNCTION ENCRYPTS THE MESSAGE
for(i=0;message[i]!='\0';i++)
encrypted_message[i]=monocipher_encr(str[i]);
// HERE I AM CALLING FUNCTION monocipher()FOR EACH ALPHABET which encrypts one alphabet at a time
printf("\n Before Encryption : %s",message);
printf("\n After Encryption : %s\n",encypted_message);
}
char monocipher_encr(char a)
{
int i;
for(i=0;i<27;i++)
{
if(a == alpha[i][0]) //IF MESSAGE CHARACTER MATCHES THE CHARACTER IN THE KEY
break;
} //THEN
return alpha[i][1]; //THIS RETURNS THE ALPHABET WHICH IS TO BE SUBSTITUTED USING KEY FILE
}
void decryption() // THIS FUNCTION ENCRYPTS THE MESSAGE
{
for(j=0;encrypted_message[j]!='\0';j++)
decrypted_message[j]=monocipher_decr(encrypted_message[j]);
// HERE I AM CALLING FUNCTION monocipher_decr() FOR EACH ALPHABET which decrypts one alphabet at a time
printf("\n Before Decryption : %s",encrypted_message);
printf("\n After Decryption : %s\n",decrypted_message);
}
char monocipher_decr(char b)
{
int j;
for(j=0;j<27;j++)
{
if(b == dealpha[j][0])
break;
}
return dealpha[j][1]; //THIS FUNCTION RETURNS THE VALUE OF ORIGINAL ALPHABET OR DECRYPTS EACH ALPHABET OF ENCRYPTED MESSAGE
}
-----------------------------------------------------------------------------------------*/