Code:
#pragma warning ( disable: 4996)
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#define bool int
int menu(); // Prints the menu
int euclid(int, int); // Performs the extended euclid's algorithm
void doaffine(char[],char[], int, int); // encrypts a file using the given keys
void affine(int, int, FILE*, FILE*); // helps the function doaffine
bool get_decrypt(int a, int b, int& c, int& d); // computes decryption keys c
// and d from given a and b.
int main() {
// Main menu of driver program
int ans = menu();
while (ans != 4) {
// Allows user to test encryption function
if (ans == 1) {
// Get pertinent info from the user.
char inputfile[100];
char outputfile[100];
printf( "Enter input file name.");
scanf("%s", &inputfile);
printf( "Enter output file name.");
scanf("%s", &outputfile);
int a,b;
printf("Enter Affine cipher values of a and b.");
scanf( "%d %d", &a,&b);
// Make the function call with this info.
doaffine(inputfile, outputfile, a, b);
}
// Allows user to test decryption key function
else if (ans == 2) {
// Gets necessary info from the user.
int a,b;
printf("Enter Affine cipher values of a and b.");
scanf( "%d %d", &a,&b);
// Calls the function and writes the output to the screen.
int c,d;
if (get_decrypt(a,b,c,d))
printf("Decrypting keys are %d and %d \n",&a,&b);
else
printf("Sorry, those are not valid keys.\n");
}
else if (ans == 3)
system("dir /p");
else if (ans > 4)
printf("Sorry, not a valid menu choice. Try again.");
ans = menu();
}
}
// Prints out user's choices.
int menu() {
int pick;
printf("Pick your menu choice :\n\n");
printf("1. Apply affine cipher to a file\n");
printf("2. Find corresponding decrypting keys for the affine cipher\n");
printf("3. Get directory listing \n");
printf("4. Quit.\n");
scanf("%d",&pick);
return pick;
}
// Opens appropriate streams and calls affine to do actual encryption.
void doaffine(char inputfile[], char outputfile[], int a, int b) {
// create a file handle
FILE *input, *output;
// Checks to see if the key is valid.
if (euclid(a,26)<0)
printf("Sorry that is not a valid affine shift key.");
else {
// Opens appropriate files
input = fopen(inputfile, "r");
output = fopen(outputfile, "w");
}
affine(a,b,input,output);
// Closes the filess
fclose(input);
fclose(output);
}
// This function does the actual translation.
void affine(int a, int b, FILE *input, FILE *output) {
// Loop until everything from the input file has been read.
char c;
while (fscanf(input,"%c",&c)!=EOF) {
// Only encrypt if it's an upper or lowercase letter.
if (c >= 65 && c <= 90)
c = char( ( a*((int)c-65)+b) + 65);
else if (c >= 97 && c <= 122)
c = char ( ( a*((int)c-97)+b) + 97);
// Output the character to the output file.
fprintf(output,"%c",c);
}
}
// Determines decryption keys c and d for the given encryption keys a and b.
bool get_decrypt(int a, int b, int& c, int& d) {
// Find the inverse of a mod 26, if it exists.
int inverse = euclid(a, 26);
// A negative value for inverse indicates no inverse, and an invalid key.
if (inverse < 0) {
c = 0;
d = 0;
return false;
}
else {
c = inverse; // From class.
d = (-1*b*c); // Look at math below to explain this.
// Accounts for the case where d ends up negative.
if (d < 0)
d += 26;
}
return true;
}
/*
Derivation of above result:
e(x) = ax + b
d(x) = cx + d
= c(ax + b) + d
= cax + bc + d
= x, as required by all cryptosystems.
Equating coefficients, we have ca = 1, and (bc + d) = 0
This means that c = a^(-1) mod 26, and d = -bc mod 26.
*/
// Precondition: n > x, and n and x are positive integers,
// Post condition: Returns x' the inverse of x (mod n), if gcd(x,n)=1 else
// returns -1*gcd(x,n)
int euclid(int x, int n) {
int t0=0, t1=1, t2;
int r0,r1,r2,q;
// Sets up the first three remainders and the quotient in Euclid's algorithm.
r0 = n;
r1 = x;
r2 = n%x;
q = n/x;
// Set's up doing the equation backwards for the inverse solution.
// The 100*26 is to ensure that t2 stays positive.
t2 = (t0 - q*t1 + 100*26) % 26;
if (r1 == 1)
t2 = 1;
// Stops when repeated division finally yields no remainder, as in Euclid's.
while (r2!=0) {
// Carries out division
int temp = r2;
q = r1/r2;
r2 = r1 - q*r2;
r1 = temp;
// Carries out next step working the equations "backwards"
if (r2!= 0) {
int temp2 = t2;
t2 = (t1 - q*t2 + 100*26) % 26;
t1 = temp2;
}
}
// Based on whether an inverse exists, either a positive value (the inverse)
// is returned or the -gcd(x,n) is returned.
if (r1 == 1)
return t2;
else
return -r1;
}