Table of Contents
Project: SECRET AGENT
A project for C/C++ Programming by Saad Malik for SPRING 2012.
This project was begun on 2/22/12 and is anticipated to take 2 days to complete. Project was completed on February 24, 2012.
Objectives
Create a program that will encipher a message (make it unreadable).
Create a second program that will take that unreadable message, and make it readable once again.
Prerequisites
In order to successfully accomplish/perform this project, the listed resources/experiences need to be consulted/achieved:
- successful completion of project #0 and solid understanding of pertinent topics
- familiarity with memory allocation via malloc(3)
- familiarity with looking up C function parameters/information in the manual
- familiarity with if statements, especially in use for error detection
- familiarity with pointers and pointer arithmetic
- familiarity with loops
- file I/O
Background
The purpose of this project is to write a program that will encipher, and a program to decipher, a message.
This will basically involve the use of if blocks, looping, command line arguments, and sorting strings into arrays (and manipulating the data therein).
Scope
This project will test your familiarity with more involved algorithms, storage, and control structures.
Encoding is the process of converting a message into a coded form.
Decoding is the reverse- retrieving that original message from an encoded form.
In this project you will write a 2 programs: one that will take a plain text message and convert it into a coded form (largely indecipherable to the regular english expecting eye) using a given cipher key, and another that will reverse the process (or decipher), when given the appropriate key.
The key is a numeric used to rotate the alphabet a set amount. Where A would normally equal 1, and Z 26, using a cipher key of 1 to shift 1 position to the right; A would now equal 2 (or B), B is now 3 (or C), and Z would be 1 (A).
Your encoding program can operate as follows:
- obtains its cipher key from a text file called “key.txt”
- or, if you prefer, use command-line arguments to provide the key
- obtains the input message from a file called “message.txt”
- if “plain.txt” is blank, or does not exist, the program should prompt the user to enter the message via STDIN
- outputs the ciphertext message to STDOUT AND saves it to a file called “cipher.txt”
- implement error checking to avoid segfaults
The decoding operation is essentially the reverse (shifting to the left). I'd suspect you could reuse much of the same logic.
Your decoding program:
- obtains its cipher key from a text file called “key.txt”
- or, if you prefer, use command-line arguments to provide the key
- obtains the input cipher from a file called “cipher.txt”
- if “cipher.txt” is blank, or does not exist, the program should prompt the user to enter the message via STDIN
- outputs the plaintext message to STDOUT AND saves it to a file called “plain.txt”
- implement error checking to avoid segfaults
If you want, you may implement both functionalities into one program so long as you provide a mechanism for the user to access both operations (but note this is not required for successful completion of this project).
Code
The encipher code:
#include <stdio.h> #include <stdlib.h> //THIS PROGRAM WILL ENCIPHER A MESSAGE GIVEN A COMMAND LINE ARGUMENT //THAT WILL BE USED AS THE ENCIPHERING KEY int main(int argc, char **argv) { FILE *in, *out; int cipher; long long int character; in = fopen("plain.txt", "r"); out = fopen("cipher.txt", "w"); //This if block will check to make sure that the user entered a cipher key //as an argument when they ran the program if(*(argv+1) == NULL) { printf("\nERROR\n"); printf("You did not provide an argument for the cipher key\n"); printf("Please run the program again, with 1 integer argument that will be the cipher key\n"); exit(1); } //This if block will ensure user does not enter an ungodly cipherkey if(atoi(*(argv+1)) > 10000) { printf("\nPlease for the love of god enter a reasonable cipher key\n"); exit(1); } //This if block will allow the user to enter a message if the input file //does not exist, else input the message from plain.txt. //The message will also be ciphered and outputted to the cipher.txt and STDOUT. char *message; message = (char*)malloc(sizeof(char) * 127); int count = 0; if(in == NULL) { printf("\nPlease enter the message you want to encrypt\n"); fgets(message, 127, stdin); printf("\nThe message that you want to encrypt is: \n"); while(*(message+count) != '\0') { printf("%c", *(message+count)); count = count+1; } int cipher = atoi(*(argv+1)); count = 0; printf("\nThe ciphered message is: \n"); while(*(message+count) != '\0') { character = 1; if(*(message+count) >= 65 && *(message+count) <= 90) { character = *(message+count) + cipher; while(character > 90) { character = character - 26; } } if(*(message+count) >= 97 && *(message+count) <= 122) { character = *(message+count) + cipher; while(character > 122) { character = character - 26; } } if(character == 1) { character = 32; } printf("%c", character); fprintf(out, "%c", character); count = count+1; } printf("\nThe enciphered message is located in cipher.txt\n"); } else { fgets(message, 127, in); printf("\nThe message that you want to encrypt is: \n"); while(*(message+count) != '\0') { printf("%c", *(message+count)); count = count+1; } int cipher = atoi(*(argv+1)); count = 0; printf("\nThe ciphered message is: \n"); while(*(message+count) != '\0') { character = 1; if(*(message+count) >= 65 && *(message+count) <= 90) { character = *(message+count) + cipher; while(character > 90) { character = character - 26; } } if(*(message+count) >= 97 && *(message+count) <= 122) { character = *(message+count) + cipher; while(character > 122) { character = character - 26; } } if(character == 1) { character = 32; } printf("%c", character); fprintf(out, "%c", character); count = count+1; } printf("\nThe enciphered message is located in cipher.txt\n"); } fclose(in); fclose(out); return (0); }
The decipher code:
#include <stdio.h> #include <stdlib.h> //THIS PROGRAM WILL TAKE A CIPHERED MESSAGE AND DECIPHER IT //AS LONG AS YOU PROVIDE THE CORRECT COMMAND LINE ARGUMENT //FOR A DECIPHER KEY int main(int argc, char **argv) { FILE *in, *out; int cipher; long long int character; in = fopen("cipher.txt", "r"); out = fopen("plain.txt", "w"); //This if block will check to make sure that the user entered a cipher key //as an argument when they ran the program if(*(argv+1) == NULL) { printf("\nERROR\n"); printf("You did not provide an argument for the cipher key\n"); printf("Please run the program again, with 1 integer argument that will be the cipher key\n"); exit(1); } //This if block will allow the user to enter a message if the input file //does not exist, else input the message from plain.txt. //The message will also be ciphered and outputted to the cipher.txt and STDOUT. char *message; message = (char*)malloc(sizeof(char) * 127); int count = 0; if(in == NULL) { printf("\nPlease enter the message you want to un-encrypt\n"); fgets(message, 127, stdin); printf("\nThe message that you want to un-encrypt is: \n"); while(*(message+count) != '\0') { printf("%c", *(message+count)); count = count+1; } int cipher = atoi(*(argv+1)); count = 0; printf("\nThe un-ciphered message is: \n"); while(*(message+count) != '\0') { character = 1; if(*(message+count) >= 65 && *(message+count) <= 90) { character = *(message+count) - cipher; while(character < 65) { character = character + 26; } } if(*(message+count) >= 97 && *(message+count) <= 122) { character = *(message+count) - cipher; while(character < 97) { character = character + 26; } } if(character == 1) { character = 32; } printf("%c", character); fprintf(out, "%c", character); count = count+1; } printf("\n"); } else { fgets(message, 127, in); printf("\nThe message that you want to un-encrypt is: \n"); while(*(message+count) != '\0') { printf("%c", *(message+count)); count = count+1; } int cipher = atoi(*(argv+1)); count = 0; printf("\nThe un-ciphered message is: \n"); while(*(message+count) != '\0') { character = 1; if(*(message+count) >= 65 && *(message+count) <= 90) { character = *(message+count) - cipher; while(character < 65) { character = character + 26; } } if(*(message+count) >= 97 && *(message+count) <= 122) { character = *(message+count) - cipher; while(character < 97) { character = character + 26; } } if(character == 1) { character = 32; } printf("%c", character); fprintf(out, "%c", character); count = count+1; } printf("\nThe un-enciphered message is located in plain.txt\n"); } fclose(in); fclose(out); return (0); }
Execution
This is the program running a cipher. Without an argument, it gives you an error to rerun with an argument.
It inputs the message from a txt file, and then enciphers it. If the file doesn't exist, then it will prompt the user to enter a message.
The enciphered message gets stored in cipher.txt.
lab46:~/src/cprog/Projects$ ./Project1 ERROR You did not provide an argument for the cipher key Please run the program again, with 1 integer argument lab46:~/src/cprog/Projects/Project1$ ./encipher 9183829183 Please for the love of god enter a reasonable cipher key lab46:~/src/cprog/Projects/Project1$ ./encipher 284 The message that you want to encrypt is: Hello my name is Pastor John xyz XYZ The ciphered message is: Fcjjm kw lykc gq Nyqrmp Hmfl vwx VWX The enciphered message is located in cipher.txt lab46:~/src/cprog/Projects/Project1$
DECIPHER
lab46:~/src/cprog/Projects/Project1$ ./decipher ERROR You did not provide an argument for the cipher key Please run the program again, with 1 integer argument that will be the cipher key lab46:~/src/cprog/Projects/Project1$ ./decipher 284 The message that you want to un-encrypt is: Fcjjm kw lykc gq Nyqrmp Hmfl vwx VWX The un-ciphered message is: Hello my name is Pastor John xyz XYZ The un-enciphered message is located in plain.txt lab46:~/src/cprog/Projects/Project1$
Reflection
The text files are created by the program, however if they do not exist the program does prompt the user to enter a message instead.
Also, the program has checks in place in case the user does not enter a command line argument.
This project really helped me fully understand how to manipulate strings of data, arrays, and command line arguments. All the other concepts used I knew fairly well, but it strongly reinforced these three big ones and I can really appreciate that.
References
In performing this project, the following resources were referenced:
http://www.asciitable.com/ – Helped deal with the ASCII aspect of the project.
http://www.cprogramming.com/tutorial/lesson9.html – This webpage helped me make sense of how to handle strings in C.
Matthew Haas also introduced the nice fgets and atoi functions.