In: Computer Science
Your task is to write a C program which performs encryption and decryption of a message using the substitution cipher algorithm.
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. 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. 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.
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:
int len = 128;
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.
*ciphertext:
QMJK JK KZWP KPHNPQ WPKKDVP! JK QMJK DAZQMPN SJAP BNZW QMP KPHNPQ WPKKDVP?
*key: DGHLPBVMJIOSWAZXCNKQFERTYU
C code:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
// encryption function
void encrypt(char *ciphertext, char *message, char *key){
int message_size=strlen(message);
for(int i=0; i<message_size; i++){
// check if character is a
alphabet, then appy substitution cipher using key
if((((int)toupper(message[i])-(int)'A')>=0) &&
(((int)toupper(message[i])-(int)'A')<=26)){
ciphertext[i]=key[(int)toupper(message[i])-(int)'A'];
}
// else message character is same as cipher
character
else{
ciphertext[i]=message[i];
}
}
}
// decryption function
void decrypt(char *ciphertext, char *message, char *key){
// find the reverse key
// that maps a cipher character to its message
character
char reverse_key[27];
reverse_key[26]='\0';
for(int i=0; i<26; i++){
reverse_key[(int)toupper(key[i])-(int)'A']='A'+i;
}
int ciphertext_size=strlen(ciphertext);
for(int i=0; i<ciphertext_size; i++){
// check if character is a
alphabet, then appy substitution cipher using reverse key
if((((int)toupper(ciphertext[i])-(int)'A')>=0) &&
(((int)toupper(ciphertext[i])-(int)'A')<=26)){
message[i]=reverse_key[(int)toupper(ciphertext[i])-(int)'A'];
}
// else message character is same as cipher
character
else{
message[i]=ciphertext[i];
}
}
}
int main(){
int message_file_present=1;
FILE* message_file = fopen("message.txt","r");
// check if message file exist
if(message_file==NULL){
message_file_present=0;
}
int cipher_file_present=1;
FILE* cipher_file = fopen("ciphertext.txt","r");
// check if ciphertext file exist
if(cipher_file==NULL){
cipher_file_present=0;
}
// error if both ciphertext and message file does
not exist
if(!(message_file_present ||
cipher_file_present)){
fprintf(stderr, "No file
'message.txt' or 'ciphertext.txt'\n");
exit(1);
}
int key_file_present=1;
FILE* key_file = fopen("key.txt","r");
// check if message file exist
if(key_file==NULL){
key_file_present=0;
fprintf(stderr, "No file
'key.txt'\n");
exit(1);
}
char key[27];
rewind(key_file);
key[26]='\0';
// maintain array to avoid repetion of
characters
int char_present[26];
for(int i=0; i<26; i++){
char_present[i]=0;
}
// incorrect key length
if(26 != fread(key, 1, 26, key_file)){
fprintf(stderr, "Length of key is not correct\n");
exit(1);
}
for(int i=0; i<26; i++){
if(!((((int)toupper(key[i])-(int)'A')>=0)
&& (((int)toupper(key[i])-(int)'A')<=26))){
fprintf(stderr, "The key contains
characters which aren’t letters\n");
exit(1);
}
if(char_present[((int)toupper(key[i])-(int)'A')]){
fprintf(stderr, "The key contains
repeated letters\n");
exit(1);
}
char_present[((int)toupper(key[i])-(int)'A')]=1;
}
if(message_file_present){
fseek(message_file, 0L,
SEEK_END);
// calculating the size of the file
int message_size = ftell(message_file);
rewind(message_file);
char message[message_size+1];
message[message_size]='\0';
if(message_size != fread(message,
1, message_size, message_file)){
exit(1);
}
char ciphertext[message_size+1];
ciphertext[message_size]='\0';
encrypt(ciphertext, message, key);
// open ciphertext file in write mode
cipher_file=fopen("ciphertext.txt","w");
if(cipher_file == NULL){
exit(1);
}
// write to file
fprintf(cipher_file,"%s",
ciphertext);
}
else{
fseek(cipher_file, 0L,
SEEK_END);
// calculating the size of the file
int ciphertext_size = ftell(cipher_file);
rewind(cipher_file);
char
ciphertext[ciphertext_size+1];
ciphertext[ciphertext_size]='\0';
if(ciphertext_size !=
fread(ciphertext, 1, ciphertext_size, cipher_file)){
exit(1);
}
char message[ciphertext_size+1];
message[ciphertext_size]='\0';
decrypt(ciphertext, message, key);
// open message file in write mode
message_file=fopen("message.txt","w");
if(message_file == NULL){
exit(1);
}
// write to file
fprintf(message_file, "%s",
message);
}
return 0;
}
When cipher text:
QMJK JK KZWP KPHNPQ WPKKDVP!
JK QMJK DAZQMPN SJAP BNZW QMP KPHNPQ WPKKDVP?
And key:
DGHLPBVMJIOSWAZXCNKQFERTYU
Message:
THIS IS SOME SECRET MESSAGE!
IS THIS ANOTHER LINE FROM THE SECRET MESSAGE?