======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 #include //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 #include //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.