-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f378273
Showing
6 changed files
with
361 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.bin | ||
*.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
CC=gcc | ||
CFLAGS=-Wall -g | ||
|
||
hill_keys: hillcipher_main.c hillcipher_keypair.c hillcipher_keypair.h | ||
$(CC) $(CFLAGS) hillcipher_main.c hillcipher_keypair.c -o hill_keys | ||
clean: | ||
rm -f *.o *.bin hill_keys |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
``` | ||
Author: Leslie Horace | ||
Purpose: Dynamically finding hill cipher encryption/decryption key pairs | ||
Version: 1.0 | ||
``` | ||
# Hill Cipher KeyPair Generator | ||
|
||
## Included files | ||
- hillcipher_main.c | ||
- Functions for creating encyrption key and computing decyrption key | ||
- hillcipher_main.h | ||
- Header file to use functions from "hillcipher_main.c" | ||
- hillcipher_main.c | ||
- simple main to demonstrate hill cipher key pair generation | ||
- Makefile | ||
- compiling program and cleaning out files | ||
|
||
## Compiling the program | ||
> make | ||
> gcc ./hillcipher_main.c ./hillcipher_keypair.c -o < outfile> | ||
## Cleaning compiled files | ||
> make clean | ||
## Running the program | ||
usage: < outfile> <enc_key filename> <dec_key filename> | ||
*output files are written in binary, use (.bin) extension* | ||
|
||
## About the program | ||
1. Creates a random square key matrix of order n, where n is in range [2, 9] | ||
+ The matrix is filled with random codes [0,26] for language [A-Z] | ||
+ Keeping the order small for demoing purposes | ||
2. Computes the modular inverse by performing elementary row operations | ||
+ Row Multiplication | ||
+ Row swap | ||
+ Row addition | ||
3. All compuations are reduced (mod 26) for language [A-Z] | ||
+ [MODULUS] macro in "hillcipher_key.c" can be modified as needed | ||
4. Generates new encryption keys untill finding one that is invertable | ||
5. Upon finding valid keypair, each key is written to the filename arguments | ||
6. The keys can be read back in for use and/or display to the console | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
/* | ||
Author: Leslie Horace | ||
File: hillcipher_keypair.h | ||
Purpose: c program to generate random hill cipher encryption/decryption key pair | ||
*/ | ||
|
||
#include <stdlib.h> // c standard library | ||
#include <stdio.h> // writing and reading files | ||
#include <string.h> // i/o file names | ||
#include "hillcipher_keypair.h" | ||
#define MODULUS 26 // hill cipher is invertable mod 26 for lanaguge [A-Z] | ||
|
||
// allocates 1dim space for any m*n matrix | ||
int *malloc1D(int m, int n) { | ||
int *X = (int*)malloc(m*n*sizeof(int)); | ||
for(int i = 0; i < m*n; i++) | ||
X[i] = 0; // initialize each index | ||
return X; // return pointer to matrix | ||
} | ||
|
||
// reads hill cipher key from a file into a n*n matrix | ||
int readKey(char * oFile, int **M, int *n){ | ||
FILE * fp = NULL; | ||
// check if file is open for reading | ||
if ((fp = fopen(oFile, "rb")) != NULL) { | ||
fread(&(*n), sizeof(int), 1, fp); // read matrix order | ||
*M = malloc1D((*n), (*n)); | ||
fread(M[0], sizeof(int), (*n)*(*n), fp); // read matrix contents | ||
fclose(fp); | ||
}else{ // here if file read error occured | ||
perror("File read error..."); | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
// writes hill cipher key from a n*n matrix to a file | ||
int writeKey(char * oFile, int *M, int n){ | ||
FILE * fp = NULL; | ||
// check if file is open for writing | ||
if ((fp = fopen(oFile, "wb")) != NULL){ | ||
fwrite(&n, sizeof(int), 1, fp); // write matrix order | ||
fwrite(M, sizeof(int), n*n, fp); // write matrix contents | ||
fclose(fp); | ||
}else{ // here if file write error occured | ||
perror("File write error..."); | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
// prints any n*m matrix | ||
void printMatrix(int *X, int m, int n){ | ||
printf("\n"); | ||
for(int i =0; i < m; i ++){ | ||
for(int j = 0; j < n; j ++){ | ||
printf("%d\t", X[i*n+j]); | ||
}printf("\n"); | ||
} | ||
printf("\n"); | ||
} | ||
|
||
// performs the extended euclidian algorithm | ||
int extEuclid(int a, int b, int *x, int *y){ | ||
int d = 0; | ||
if(a == 0){ // error case: a,b are not relatively prime | ||
*x=a; | ||
*y=a+1; | ||
d = b; | ||
}else{ // recursive case: a,b are relatively prime | ||
int x_tmp = 0, y_tmp = 0; | ||
// backwards substitution to find inverses s.t. ax+by=1 | ||
d = extEuclid(b%a, a, &x_tmp, &y_tmp); | ||
*x = y_tmp - (x_tmp * (b/a)); | ||
*y = x_tmp; | ||
} | ||
return d; // return the GCD | ||
} | ||
|
||
// calculates and returns the positive remainder of mod 26 | ||
int positiveMod(int a) { | ||
int r = a % MODULUS; | ||
if (r < 0){ | ||
r += MODULUS; | ||
} | ||
return r; | ||
} | ||
|
||
// initializes K = key matrix and A = augmented matrix [K | I], where I = identity | ||
void initKeys(int * K, int * A, int n, int m){ | ||
for(int i =0; i < n; i ++){ | ||
for(int j =0; j < n; j++){ | ||
K[i*n+j] = A[i*m+j] = rand() % 26; | ||
// set RIGHT half of A[K | I] as identity matrix | ||
if(i==j){ | ||
A[i*m+(j+n)] = 1; // diagonal 1 | ||
}else{ | ||
A[i*m+(j+n)] = 0; // all else 0 | ||
} | ||
} | ||
} | ||
} | ||
|
||
// row operation: swaps the pivots row with the target row | ||
void swapRow(int *A, int target, int pivot,int m){ | ||
int x=0; | ||
for(int j=0; j < m; j++){ | ||
x = A[pivot*m+j]; // temp = A[pivot][j] | ||
A[pivot*m+j] = A[target*m+j]; // A[pivot][j] = A[target][j] | ||
A[target*m+j] = x; // A[target][j] = temp | ||
} | ||
} | ||
|
||
// row operation: scale the row by multiplying with the pivots modular inverse | ||
int scaleRow(int *A, int pivot, int n, int m){ | ||
int x = 0, y = 0; | ||
// loops starts with the pivot's row | ||
for (int i=pivot; i < n; i++){ | ||
// check if current index A[i][pivot] is invertable (mod 26) | ||
if(extEuclid(A[i*m+pivot], MODULUS, &x, &y) == 1){ | ||
// if current row is not the pivot row, then swap rows | ||
if(i != pivot){ | ||
swapRow(A, i, pivot, m); | ||
} | ||
// multiple the row by the pivot's inverse | ||
for(int j =0; j < m; j++){ | ||
A[pivot*m+j] *= x; // A[pivot][j] = A[pivot][pivot]^-1 * A[pivot][j] | ||
A[pivot*m+j] = positiveMod(A[pivot*m+j]); // reduce by (mod 26) | ||
} | ||
return 1; // return 1(true) = is invertable mod 26 | ||
} | ||
} | ||
return 0; // return 0 (false) = not invertable mod 26 | ||
} | ||
|
||
// row operation: subtract each row index by a multiple of pivots row index | ||
void subtractRow(int *A, int pivot, int n, int m){ | ||
int x = 0; | ||
for (int i=0; i < n; i++){ | ||
// check if the current row is not the pivot row | ||
if(i != pivot){ | ||
x = A[i*m+pivot]; // x = A[i][pivot] | ||
for(int j=0; j < m; j++){ | ||
A[i*m+j] -= (x * A[pivot*m+j]); // A[i][j] = A[i][j] - (A[i][pivot] * A[pivot][j]) | ||
A[i*m+j] = positiveMod(A[i*m+j]); // reduce by (mod 26) | ||
} | ||
} | ||
} | ||
} | ||
|
||
// creates a random key and computes it inverse, continues until invertable key pair is found | ||
void findInvertableKey(int * K, int * A, int n, int m){ | ||
int valid = 0; | ||
do{ | ||
initKeys(K, A, n, m); // intilize a new key matrix and corresponding augmented matrix | ||
for(int i=0; i < n; i++){ | ||
// check if scaleRow function returns 1(true) for success | ||
if(scaleRow(A, i, n, m) == 1){ | ||
// perform row subtraction to tranform A[K | I] => A[I | K^-1] | ||
subtractRow(A, i, n, m); | ||
valid = 1; | ||
} else{ // here if the key is not invertable, stop inner loop | ||
valid = 0; | ||
break; | ||
} | ||
} | ||
}while(valid == 0); // loops until invertable key is found | ||
} | ||
|
||
// set new matrix X = K^-1 (from right half of transformed A[I|K^-1]) for writing | ||
void getInverseKey(int * X, int * A, int n, int m){ | ||
for(int i =0; i < n; i++){ | ||
for(int j =0; j < n; j++){ | ||
X[i*n+j] = A[i*m+(j+n)]; // X[i][j] = I[i][j] in A[K|I] | ||
} | ||
} | ||
} | ||
|
||
// primary function for creating a new hill cipher key pair | ||
int createKeyPair(char * ekey_fname, char * dkey_fname){ | ||
|
||
int *K, *A; // K = key matrix pointer, A = augmented matrix pointer | ||
int n = (rand() % 8) + 2, m = 2*n; // n = random [2-9] matrix order, m = 2*n for augmented matrix traversals | ||
|
||
// allocate space for key and augmented matrices | ||
K = malloc1D(n, n); | ||
A = malloc1D(n, m); | ||
|
||
// find a invertable key pair | ||
findInvertableKey(K, A, n, m); | ||
|
||
// write the encyrption key to specfied filename | ||
printf("\nWriting encryption key to file '%s'...\n", ekey_fname); | ||
int res = writeKey(ekey_fname, K, n); | ||
if(res == 0){ // if encyrption key was successfully written, get the inversekey | ||
getInverseKey(K, A, n, m); | ||
// write the decryption key to specfied filename | ||
printf("\nWriting decryption key to file '%s'...\n", dkey_fname); | ||
res = writeKey(dkey_fname, K, n); | ||
} | ||
|
||
// deallocate space for matrices | ||
free(A); | ||
free(K); | ||
return res; // return result for writing keys to files | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
Author: Leslie Horace | ||
File: hillcipher_keypair.h | ||
Purpose: header file to call functions necessary for creating and utilizing encyrption/decryption key pairs | ||
*/ | ||
|
||
#ifndef HILLCIPHER_KEYPAIR_ | ||
#define HILLCIPHER_KEYPAIR_ | ||
|
||
/* | ||
allocates space for a 1d array of n*m size | ||
returns a (int *) pointer to the array | ||
*/ | ||
int *malloc1D(int m, int n); | ||
|
||
/* | ||
reads a binary file key into a matrix | ||
params: input filename.bin, M = pointer to matrix, n = matrix order | ||
returns 1 (error) or 0 (success) | ||
*/ | ||
int readKey(char * oFile, int **M, int *n); | ||
|
||
|
||
/* | ||
prints a m*n matrix to the console | ||
params: matrix pointer X, m = row size, n = col size | ||
*/ | ||
void printMatrix(int *X, int m, int n); | ||
|
||
/* | ||
calculates GCD(a,b) = d, where ax + by = d | ||
params: a = integer, b = modulus, x = a inverse, and y = b inverse | ||
returns d, inverse x and y are returned as arguments | ||
*/ | ||
int extEuclid(int a, int b, int *x, int *y); | ||
|
||
/* | ||
computes positive remainder = a (mod 26) | ||
returns the remainder | ||
*/ | ||
int postiveMod(int a); | ||
|
||
/* | ||
generates a random matrix order n from [2,9] | ||
creates random n*n encyrption and decyrption key matrices | ||
writes out both keys to their specified file names | ||
params: encryption key file name, decyrption key file name | ||
returns 1 (error) or 0 (success) | ||
*/ | ||
int createKeyPair(char * ekey_fname, char * dkey_fname); | ||
|
||
|
||
#endif /* MATRIX_KEY_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
Author: Leslie Horace | ||
File: hillcipher_main.c | ||
Purpose: c program to demonstrate functions provided by hillcipher_keypair.h | ||
*/ | ||
|
||
#include <stdlib.h> // c standard library | ||
#include <stdio.h> // writing and reading files | ||
#include <string.h> // i/o file names | ||
#include <time.h> // for seeding randomness | ||
#include "hillcipher_keypair.h" | ||
|
||
|
||
/* main entry point for generating hill cipher encryption/decryption keys */ | ||
int main(int argc, char **argv){ | ||
|
||
if(argc != 3){ | ||
printf("usage: %s <enc key filename> <dec key filename>\n", (char*)argv[0]); | ||
exit(EXIT_FAILURE); | ||
} | ||
char * ekey_fn = argv[1]; | ||
char * dkey_fn = argv[2]; | ||
|
||
srand(time(NULL)); // time seed for randomness | ||
|
||
printf("\nGenerating encryption/decryption key pairs...\n"); | ||
if(createKeyPair(ekey_fn, dkey_fn) == 1){ | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
int * ekey, * dkey, n; // key matrices and matrix order | ||
|
||
printf("\nReading key files '%s' and '%s'...\n", ekey_fn, dkey_fn); | ||
|
||
if(readKey(ekey_fn, &ekey, &n) != 0){ | ||
exit(EXIT_FAILURE); | ||
} | ||
printf("\nEncryption Key ['%s']:\n", ekey_fn); | ||
printMatrix(ekey, n, n); | ||
free(ekey); | ||
|
||
if(readKey(dkey_fn, &dkey, &n) != 0){ | ||
exit(EXIT_FAILURE); | ||
} | ||
printf("\nDecryption Key ['%s']:\n", dkey_fn); | ||
printMatrix(dkey, n, n); | ||
free(dkey); | ||
|
||
exit(EXIT_SUCCESS); | ||
} |