# include <stdio.h>

# include <stdlib.h>

# include <string.h>

# include <time.h>


# define _TRUE_ 1

# define _strLength_ 200 // 臾몄옄?댁쓽 湲몄씠

# define _ALPHA_ 27

# define _R_ 2

# define _C_ 2

# define _x_ *


char G_alphabet[_ALPHA_] = "abcdefghi jklmnopqrstuvwxyz";


typedef struct _affine {

int key[_R_][_C_];    // Encrypt key

int RevKey[_R_][_C_]; // Decrypt key

int detKey; // determinant(A)

int rKey; // determinant(A^-1)

char plainText[_strLength_];

int* plainTextVector;

int plainTextSize;

char cipherText[_strLength_];

int* cipherTextVector;

char decryptText[_strLength_];

int* decryptTextVector;

}affine, *ptrAffine;


// +++++++++++++++++ prototype of function +++++++++++++++++++

void Err_Function(char* errMassage); // -----------------> [1]

void Init_Function(affine** stu); // --------------------> [2]

void RandomKey_Function(affine** stu); // ---------------> [3]

int Detert_Function(affine** stu); // -------------------> [4]

void plainText_Function(affine** stu); // ---------------> [5]

void plainText_Vector_Init_Function(affine** stu); // ---> [6]

void cipherText_Vector_Init_Function(affine** stu); // --> [7]

void encrypt_Function(affine** stu); // -----------------> [8]

void reverseKey_Function(affine** stu); // --------------> [9]

void decryptText_Vector_Init_Function(affine** stu); // -> [10]

void decrypt_Function(affine** stu); // -----------------> [11]

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


int main(void) {

srand((unsigned)time(NULL));

ptrAffine stu = NULL;

Init_Function(&stu);

RandomKey_Function(&stu);

plainText_Function(&stu);

plainText_Vector_Init_Function(&stu);

cipherText_Vector_Init_Function(&stu);

encrypt_Function(&stu);

reverseKey_Function(&stu);

decryptText_Vector_Init_Function(&stu);

decrypt_Function(&stu);

return 0;

} // end of main function


void Err_Function(char* errMassage) { // --> [1]

fprintf(stderr, "%s \n", errMassage);

exit(0); // END

} // end of Err_Function


void Init_Function(affine** stu) { // -----> [2]

(*stu) = (ptrAffine)malloc(sizeof(affine));

if ( (*stu) == NULL ) {

Err_Function("memory allocation fail !!");

} else { // (*stu) != NULL

memset( (*stu), 0, sizeof(affine));

/*

int key[_R_][_C_];

int RevKey[_R_][_c_]; // Decrypt key

char plainText[_strLength_];

char cipherText[_strLength_];

char decryptText[_strLength_];

*/

}

} // end of Init_Function


void RandomKey_Function(affine** stu) { //  [3]

int i, j; // index

while ( _TRUE_ ) {

for (i = 0; i < _R_ ; i++) {

for (j = 0; j < _C_ ; j++) {

(** stu).key[i][j] = rand()%_ALPHA_;

}

}

if (Detert_Function(stu)!= 0) {

for (i = 0; i < _R_ ; i++) {

for (j = 0; j < _C_ ; j++) {

printf("%02d ", (** stu).key[i][j]);

} printf("\n");

}

printf("\n\n\n");

//sleep(1);

//system("cls");

break;

} else {

printf(" ======================== \n");

for (i = 0; i < _R_ ; i++) {

for (j = 0; j < _C_ ; j++) {

printf("%d ", (** stu).key[i][j]);

} printf("\n");

}

printf(" ======================== \n");

}

} // while

} //end of RandomKey_Function


int Detert_Function(affine** stu) {

/*

a[0][0] a[0][1]

a[1][0] a[1][1]


det(A) = (a[0][0] x a[1][1]) - (a[0][1] x a[1][0])

*/

(** stu).detKey = ( ( (** stu).key[0][0] _x_ (** stu).key[1][1] ) - 

           ( (** stu).key[0][1] _x_ (** stu).key[1][0] ) )%_ALPHA_;

if ((** stu).detKey < 0) {

(** stu).detKey += _ALPHA_;

}

printf("(** stu).detKey => %d \n", (** stu).detKey);

return (** stu).detKey;

} // end of Detert_Function 


void plainText_Function(affine** stu) {

int tempSize = 0;

fprintf(stdout, "%s", "Plz plainText input : ");

gets((** stu).plainText);

fflush(stdin);

//system("cls");

(** stu).plainTextSize = strlen((** stu).plainText);

printf("echo] plainText is [ %s ] \n", (** stu).plainText);

} // end of plainText_Function


void plainText_Vector_Init_Function(affine** stu) {

int i, j;// index

(** stu).plainTextVector = (int*)malloc(sizeof(int) _x_ (**stu).plainTextSize);

if ((** stu).plainTextVector == NULL) {

Err_Function("memory allocation fail !!");

} else {

memset((** stu).plainTextVector, 0, sizeof(int) _x_ (**stu).plainTextSize);

for (i = 0; i < (**stu).plainTextSize; i++) {

for (j = 0; j < _ALPHA_; j++) {

if ( (**stu).plainText[i] == G_alphabet[j] ) {

(**stu).plainTextVector[i] = j;

break;

}

}

}

}

printf("echo] plainTextVector => ");

for (i = 0; i < (**stu).plainTextSize; i++) {

printf("%d ", (**stu).plainTextVector[i]);

} printf("\n");

} // end of plainText_Vector_Init_Function


void cipherText_Vector_Init_Function(affine** stu) {

int i;

(** stu).cipherTextVector = (int*)malloc(sizeof(int) _x_ (**stu).plainTextSize);

if ((** stu).cipherTextVector == NULL) {

Err_Function("memory allocation fail !!");

} else {

memset((** stu).cipherTextVector, 0, sizeof(int) _x_ (**stu).plainTextSize);

}

printf("echo] cipherTextVector => ");

for (i = 0; i < (**stu).plainTextSize; i++) {

printf("%2d ", (**stu).cipherTextVector[i]);

} printf("\n");

} // end of plainText_Vector_Init_Function 


void encrypt_Function(affine** stu) {

int i; // index

int R = 0; // ROW

int C = 0; /// COL

int tempSum_front = 0;

int tempSum_back = 0;

int temp1 = 0;

int temp2 = 0;

int temp3 = 0;

int temp4 = 0;

int result = 0;

// 0 1 2 3 4 5 6 7 8 9

// 0   2   4   6   8

if ((**stu).plainTextSize %2 == 0) { // (**stu).plainTextSize %2 == 0

for (i = 0; i <= (**stu).plainTextSize-2; i +=2) {

while (_TRUE_) {

// front ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

printf(" i=> [%d] \n", i);

temp1   += ( (**stu).plainTextVector[i] _x_ (**stu).key[R][C] );

temp2   += ( (**stu).plainTextVector[i+1] _x_ (**stu).key[R+1][C] );

tempSum_front  = (temp1 + temp2)%_ALPHA_;

printf("tempSum_front => %d \n", tempSum_front);

(**stu).cipherTextVector[result++] = tempSum_front;


// back +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

temp3   += ( (**stu).plainTextVector[i] _x_ (**stu).key[R][C+1] );

temp4   += ( (**stu).plainTextVector[i+1] _x_ (**stu).key[R+1][C+1] );

tempSum_back  = (temp3 + temp4)%_ALPHA_;

printf("tempSum_back => %d \n", tempSum_back);

(**stu).cipherTextVector[result++] = tempSum_back;

tempSum_front = 0;

tempSum_back = 0;

temp1 = 0;

temp2 = 0;

temp3 = 0;

temp4 = 0;

break;

}

}   

// 0 1 2 3 4 5 6 7 8 

// 0   2   4   6   8

/*

else { // (**stu).plainTextSize %2 != 0

for (i = 0; i <= (**stu).plainTextSize-3; i +=2) {

while (_TRUE_) {

// front ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

temp1   += ( (**stu).plainTextVector[i] _x_ (**stu).key[R][C] );

temp2   += ( (**stu).plainTextVector[i+1] _x_ (**stu).key[R+1][C] );

tempSum_front  = (temp1 + temp2)%_ALPHA_;

(**stu).cipherTextVector[result] = tempSum_front;


// back +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

temp3   += ( (**stu).plainTextVector[i] _x_ (**stu).key[R][C+1] );

temp4   += ( (**stu).plainTextVector[i+1] _x_ (**stu).key[R+1][C+1] );

tempSum_back  = (temp1 + temp2)%_ALPHA_;

(**stu).cipherTextVector[result++] = tempSum_back;

tempSum_front = 0;

tempSum_back = 0;

temp1 = 0;

temp2 = 0;

temp3 = 0;

temp4 = 0;

break;

}

}   

}

*/

for (i = 0; i < (**stu).plainTextSize; i++) {

printf("%d ", (**stu).cipherTextVector[i]);

} printf("\n");

for (i = 0; i < (**stu).plainTextSize; i++) {

(**stu).cipherText[i] = G_alphabet[(**stu).cipherTextVector[i]]; 

}

printf("echo] cipherText is [%s] \n", (**stu).cipherText);

} // end of encrypt_Function


/*

int key[_R_][_C_];    // Encrypt key

int RevKey[_R_][_C_]; // Decrypt key

int detKey; // determinant(A)

int revKey; // determinant(A^-1)

char plainText[_strLength_];

int* plainTextVector;

int plainTextSize;

char cipherText[_strLength_];

int* cipherTextVector;

char decryptText[_strLength_];

*/


void reverseKey_Function(affine** stu) {

int n; // index

int i, j, k; // index

int temp = 0;

for (n = 1; ;n++) {

if ( 1 == ((**stu).detKey _x_ n)% _ALPHA_ ) {

(**stu).rKey = n;

break;

}

printf("reverseKey => %d \n", (**stu).rKey);

(**stu).RevKey[0][0] = (**stu).rKey _x_ (**stu).key[1][1];

(**stu).RevKey[0][1] = (**stu).rKey _x_ ( (-1) _x_ (**stu).key[0][1] );

(**stu).RevKey[1][0] = (**stu).rKey _x_ ( (-1) _x_ (**stu).key[1][0] );

(**stu).RevKey[1][1] = (**stu).rKey _x_ (**stu).key[0][0];

for (i = 0; i < _R_; i++) {

for (j = 0; j < _C_; j++) {

if ((**stu).RevKey[i][j] < 0) {

temp = (**stu).RevKey[i][j];

for ( k = 1; ; k++) {

temp = temp + (_ALPHA_ * k);

if ( temp >= 0) {

temp = temp%_ALPHA_;

(**stu).RevKey[i][j] = temp;

break;

} else { // temp < 0

temp = (**stu).RevKey[i][j];

}

}

} else { // (**stu).RevKey[i][j] >= 0

(**stu).RevKey[i][j] %=_ALPHA_; 

}


}

for (i = 0; i < _R_; i++) {

for (j = 0; j < _C_; j++) {

printf("%02d ", (**stu).RevKey[i][j]);

} printf("\n");

} printf("\n");


} // end of reverseKey_Function


void decryptText_Vector_Init_Function(affine** stu) {

int i;

(** stu).decryptTextVector = (int*)malloc(sizeof(int) _x_ (**stu).plainTextSize);

if ((** stu).decryptTextVector == NULL) {

Err_Function("memory allocation fail !!");

} else { // (** stu).decryptTextVector != NULL

memset((** stu).decryptTextVector, 0, sizeof(int) _x_ (**stu).plainTextSize);

}

printf("echo] decryptTextVector => ");

for (i = 0; i < (**stu).plainTextSize; i++) {

printf("%2d ", (**stu).decryptTextVector[i]);

} printf("\n");

} // end of decryptText_Vector_Init_Function


void decrypt_Function(affine** stu) {

int i; // index

int R = 0; // ROW

int C = 0; /// COL

int tempSum_front = 0;

int tempSum_back = 0;

int temp1 = 0;

int temp2 = 0;

int temp3 = 0;

int temp4 = 0;

int result = 0;

// 0 1 2 3 4 5 6 7 8 9

// 0   2   4   6   8

if ((**stu).plainTextSize %2 == 0) { // (**stu).plainTextSize %2 == 0

for (i = 0; i <= (**stu).plainTextSize-2; i +=2) {

while (_TRUE_) {

// front ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

printf(" i=> [%d] \n", i);

temp1   += ( (**stu).cipherTextVector[i] _x_ (**stu).RevKey[R][C] );

temp2   += ( (**stu).cipherTextVector[i+1] _x_ (**stu).RevKey[R+1][C] );

tempSum_front  = (temp1 + temp2)%_ALPHA_;

printf("tempSum_front => %d \n", tempSum_front);

(**stu).decryptTextVector[result++] = tempSum_front;


// back +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

temp3   += ( (**stu).cipherTextVector[i] _x_ (**stu).RevKey[R][C+1] );

temp4   += ( (**stu).cipherTextVector[i+1] _x_ (**stu).RevKey[R+1][C+1] );

tempSum_back  = (temp3 + temp4)%_ALPHA_;

printf("tempSum_back => %d \n", tempSum_back);

(**stu).decryptTextVector[result++] = tempSum_back;

tempSum_front = 0;

tempSum_back = 0;

temp1 = 0;

temp2 = 0;

temp3 = 0;

temp4 = 0;

break;

}

}   

}

for (i = 0; i < (**stu).plainTextSize; i++) {

printf("%d ", (**stu).decryptTextVector[i]);

} printf("\n");

for (i = 0; i < (**stu).plainTextSize; i++) {

(**stu).decryptText[i] = G_alphabet[(**stu).decryptTextVector[i]]; 

}

printf("echo] decryptText is [%s] \n", (**stu).decryptText);

}