Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Author: Jakob Forde
- Date: April 7th, 2020
- Description: Allows the user to give a text file to be encrypted using a Vigénere cipher and a
- key. The encrypted file can then be translated back into regular text using that
- same key.
- */
- #include <stdio.h>
- #include <stdlib.h>
- //This function is used to generate the size of a C-string. Used in Encrypt/Decrypt for key size.
- int CalcSize(char checkSize[]) {
- int i = 0;
- int size = 0;
- while (checkSize[i] != '\0') {
- i++;
- size++;
- }
- return size;
- }
- //Used to create Vigenere board for encryption/decryption. Creates a specially-sized board based off of the key and text file
- char** VigenereBoard(char newKey[], off_t fileSize) {
- int i;
- int j;
- int inc = 0;
- //Dynamically allocating an array thats fileSize x 94
- char** myArray = (char**)malloc(fileSize*sizeof(char*)+1);
- for (i=0; i<fileSize; i++){
- myArray[i] = malloc(94*sizeof(char));
- }
- //Filling the cipher correctly. The first column contains the key stretched to be the length of the text file (newKey).
- //The first row finishes out the ASCII alphabet started with the first letter of the newKey and repeats the alphabet
- //just to fill 94 characters (the entire ASCII alphabet). The second row and so on do likewise.
- for (i=0; i<fileSize; i++) {
- inc = 0;
- for (j=0; j<94; j++) {
- if (newKey[i] == ' ') { //There's no need to encrypt/decrypt the space, which is all characters in not alphabet
- break;
- } else {
- myArray[i][j] = newKey[i]+inc; //Starting with newKey letter and continuing out the ASCII alphabet for the ith row
- inc++;
- if ((int)newKey[i]+ inc == 127) //127 is out of the bounds of the ASCII alphabet, so it will reset back to '!'
- inc = 33-(int)newKey[i];
- }
- }
- }
- return myArray;
- }
- //This cracks the cipher based off of a key, textfile, and output file name
- void Decrypt(char key[], char phrase[], char outputName[], off_t fileSize) {
- int i;
- int j = 0;
- int sizeOfKey;
- int keyLocation;
- int cipherLetter;
- char decrypt[fileSize];
- //Calculating the size of phrase and key using a function, will be helpful later.
- sizeOfKey = CalcSize(key);
- //Creating a new key. The new key is just the key but made to be as long as the text file, repeating letters if necessary.
- char newKey[fileSize];
- for (i=0; i<fileSize; i++) {
- if ((int)phrase[i] <=32) { //If the file contains any spaces, tabs, enters, etc. they are stored as a "space" in the newKey
- newKey[i] = 32;
- } else {
- newKey[i] = key[j];
- j++;
- if (j==sizeOfKey) //This will reset the key in case it is shorter than the phrase
- j = 0;
- }
- }
- //Calls function to dynamically allocate a properly sized board. More info in VigenereBoard function.
- char** myArray = VigenereBoard(newKey, fileSize);
- //Decrypting the message. Starts each row by counting the distance from the key to the cipher letter. That
- //distance is the letter of the transation.
- for (i=0; i<fileSize; i++) {
- cipherLetter = 0;
- if (newKey[i] == ' ') { //Allows decrypted message to retain spaces, enters, tabs, etc.
- decrypt[i] = phrase[i];
- } else {
- for (j=0; j<94; j++) {
- if (phrase[i] == myArray[i][j])
- cipherLetter = j;
- }
- decrypt[i] = (char) cipherLetter+33; //1st letter of ASCII alphabet is 33, '!'
- }
- }//end of for loop
- //Writing the encrypted file to user specifications
- FILE *toWrite;
- char buffer[1];
- toWrite = fopen(outputName, "w");
- fwrite(decrypt, sizeof(buffer), fileSize, toWrite);
- fclose(toWrite);
- //Deleting the dynamically allocated array
- for(int i=0; i<fileSize; i++)
- free(myArray[i]);
- free(myArray);
- }
- //This generates an encryption based off of a key and the text file given by the user
- void Encrypt(char key[], char* phrase, char outputName[], off_t fileSize) {
- int i;
- int j = 0;
- int sizeOfKey;
- int phraseLocation;
- int keyLocation;
- char cipher[fileSize];
- //Calculating the size of phrase and key using a function, will be helpful later
- sizeOfKey = CalcSize(key);
- //Creating a new key. The new key is just the key but made to be as long as the text file, repeating letters if necessary.
- char newKey[fileSize];
- for (i=0; i<fileSize; i++) {
- if ((int)phrase[i] <=32) { //If the file contains any spaces, tabs, enters, etc. they are stored as a "space" in the newKey
- newKey[i] = 32;
- } else {
- newKey[i] = key[j];
- j++;
- if (j==sizeOfKey) //This will reset the key in case it is shorter than the phrase
- j = 0;
- }
- }
- //Calls function to dynamically allocate a properly sized board. More info in VigenereBoard function.
- char** myArray = VigenereBoard(newKey, fileSize);
- //Using the board generated above to create a translation. For every letter of the newKey, it searches for the ASCII
- //alphabet location of the phrase letter. Each row starts from the ASCII alphabet beginning with the key, but the search
- //starts from the actual beginning of the ASCII alphabet. Rotating Caesar cypher.
- for (i=0; i<fileSize; i++) {
- if (newKey[i] == ' ') {
- cipher[i] = phrase[i]; //This allows the encryption to retain spaces, tabs, enters, etc. of the original file
- } else {
- phraseLocation = (int) phrase[i]-33; //33 is first letter of the ASCII alphabet (!)
- cipher[i] = myArray[i][phraseLocation];
- }
- }
- //Writing the encrypted file to user specifications
- FILE *toWrite;
- char buffer[1];
- toWrite = fopen(outputName, "w");
- fwrite(cipher, sizeof(buffer), fileSize, toWrite);
- fclose(toWrite);
- //Deleting the dynamically allocated array
- for(i=0; i<fileSize; i++) {
- free(myArray[i]);
- }
- free(myArray);
- }
- int main() {
- typedef enum {false, true}bool; //create boolean value using typdef/enum for readability
- int choice;
- bool menuCycle = true;
- bool programOn = true;
- //Beginning menu, asks the user to read or write an encryption
- while (programOn == true) {
- while (menuCycle == true) {
- printf("\n----------------VIGÉNERE CIPHER----------------\n");
- printf("Press 1 to decrypt a file.\n");
- printf("Press 2 to encrypt a file.\n");
- printf("Press 3 to exit.\n");
- scanf("%d", &choice);
- if (choice==1 || choice==2 || choice==3)
- menuCycle = false;
- else
- printf("Try again\n");
- } // end of menuCycle while loop
- menuCycle = true;
- //switch case for reading or writing
- switch (choice) {
- //Variables used for both cases:
- //Maximum size of key or filename is 128 characters
- char fileName[128];
- char outputName[128];
- char key[128];
- char buffer[100];
- off_t fileSize; //Using off_t because it can hold more space than int just in case file is VERY large
- FILE* infile;
- case 1:
- printf("----------------DECRYPTING A FILE----------------\n");
- //Asking user for the file to decrypt
- while (menuCycle == true) {
- printf("Please enter the name of the file you would like to decrypt:\n");
- scanf("%s", fileName);
- //Creating a file pointer. If the file name can't be found, program will
- //ask user to input a valid name.
- infile = fopen(fileName, "r");
- if (infile == NULL) //file can't be found
- printf("This file does not exist. Please try again\n");
- else {
- menuCycle = false;
- }
- } // end of picking file name loop
- //This traverses the entirety of the file and stores its size in bytes in fileSize.
- fseek(infile, 0, SEEK_END);
- fileSize = ftell(infile);
- fseek(infile, 0, SEEK_SET);
- //Dynamically allocating c-string to fit exact size of the file given by the user.
- char* text = (char*) malloc(fileSize*sizeof(char));
- //Storing text in file in c string, doing it in sizeof(buffer) chunks, which is 100 bytes at a time
- //Do this for a total of fileSize times.
- fread(text, sizeof(buffer), fileSize, infile);
- printf("File read successfully!\n");
- fclose(infile);
- //User input for correct key and the output file name
- printf("Enter the key (NO SPACES ALLOWED):\n");
- scanf("%s", key);
- printf("What should the decrypted file be called?\n");
- scanf("%s", outputName);
- //Calling decrypt function to decrypt file using the correct key and placing it in a file named by the user
- Decrypt(key, text, outputName, fileSize);
- free(text);
- printf("FILE DECRYPTED!\n");
- menuCycle = true;
- break; //end of case 1
- case 2:
- printf("----------------ENCRYPTING A FILE----------------\n");
- //Asking user for the file to encrypt
- while (menuCycle == true) {
- printf("Please enter the name of the file you would like to encrypt:\n");
- scanf("%s", fileName);
- //Creating a file pointer. If the file name can't be found, program will
- //ask user to input a valid name.
- infile = fopen(fileName, "r");
- if (infile == NULL) //file can't be found
- printf("This file does not exist. Please try again\n");
- else {
- menuCycle = false;
- }
- } // end of picking file name loop
- //This traverses the entirety of the file and stores its size in bytes in fileSize.
- fseek(infile, 0, SEEK_END);
- fileSize = ftell(infile);
- fseek(infile, 0, SEEK_SET);
- //Dynamically allocating c-string to fit exact size of the file given by the user.
- text = (char*) malloc(fileSize*sizeof(char));
- //Store text in file in the c-string, doing it in sizeof(buffer) chunks, which is 100 bytes at a time.
- //Do this for a total of fileSize times.
- fread(text, sizeof(buffer), fileSize, infile);
- printf("File read successfully!\n");
- fclose(infile);
- //Asking user for the key and the file output name
- printf("Enter your key (NO SPACES ALLOWED):\n");
- scanf("%s", key);
- printf("What should the encrypted file be called?\n");
- scanf("%s", outputName);
- //Calling encrypt function to create the encryption out of text file, key, and placing it in a file the user named
- Encrypt(key, text, outputName, fileSize);
- free(text);
- printf("FILE ENCRYPTED!\n");
- menuCycle = true;
- break; //end of case 2
- case 3: //User exits the menu and ends the program
- programOn = false;
- break;
- } // end of switch statement
- } //end of entire-program loop
- return 0;
- } // end of main
Add Comment
Please, Sign In to add comment