Hello to all
I am trying to make a program that implements the Vigenere known algorith for cryptography ...
Vigenère cipher - Wikipedia, the free encyclopedia
I have done the lot of the job ... But i have to throw out the characters that they aren't valid letters after I will give the choice to user to give text from terminal or from a file. Anyway for now I have done this :
Code:
/********************************************
* Description: Simple Vigenere example program
* Licence : Public
* ******************************************/
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define MAX_ROWS 26
#define MAX_COLS 26
#define MAX_LEN_PLAINTEXT 30 + 1
#define MAX_LEN_KEY 30 + 1
#define S_CHAR 'A' // Starting char of latin alphabet
#define E_CHAR 'Z' // Ending char of latin alphabet
#define MOD 26
#if 1
#define INFO "*****************************************\n"\
"* Author: Kwstas Tsit *\n"\
"* Email: [email protected] *\n"\
"* Date: 19/12/2014 *\n"\
"* Type : Encryption/Decryption *\n"\
"* Method: Vigenere Algorithm *\n"\
"* More info: Google Vigenere Algorithm *\n"\
"*****************************************\n"\
#define CRYPTO_LABEL " ******* ****** * * ***** ******* *******\n" \
"* * * * * * * * * *\n" \
"* ****** ***** ***** * * *\n" \
"* ** * * * * *\n" \
"******* * * * * * *******\n" \
#endif
char *vigenere_crypto( char *plaintext, char *key);
char *vigenere_decrypto( char *encrypted , char *key);
void tab_recta( char tabula_recta[MAX_ROWS][MAX_COLS] );
void print_tab_recta( char tabula_recta[MAX_ROWS][MAX_COLS] );
int read_line( char *str , int n);
char* key_repeat( char *key , char *plaintext , int KeyLen );
char tabula_recta[MAX_ROWS][MAX_COLS];
/*************************************************
* main function , call the subroutines
* of tab_recta table , encryption - decryption.
* ***********************************************/
int main(void)
{
char plaintext[MAX_LEN_PLAINTEXT]={'\0'};
char *key = NULL;
int KeyLen;
printf("%s" , CRYPTO_LABEL);
printf("\n %s" , INFO);
tab_recta( tabula_recta );
printf("\n");
//print_tab_recta( tabula_recta );
printf("Give the plaintext(up to 30 characters) : ");
read_line( plaintext , MAX_LEN_PLAINTEXT ); //read the message.
key = calloc (MAX_LEN_KEY , sizeof(char));
if( key == NULL ){
printf("Error: malloc faild in key");
exit(EXIT_FAILURE);
}
printf("Give the key: ");
KeyLen = read_line( key , MAX_LEN_KEY ); // the actual length of user's key.
key_repeat( key , plaintext , KeyLen ); // key repeat if it is necessary.
puts(key);
printf("\n Cipher: %s " , vigenere_crypto(plaintext, key) );
printf("\n Plaintext: %s ", vigenere_decrypto( plaintext , key) );
free(key);
return 0;
}
/********************************************************
* tab_recta table filling function , uses an 2D array
* in order to make the tab_recta square table.
* ******************************************************/
void tab_recta( char tabula_recta[MAX_ROWS][MAX_COLS] )
{
int pos , row , col;
for( row=0; row < MAX_ROWS; row++){
pos = 0;
for( col=0; col < MAX_COLS; col++){
if( S_CHAR+row+col > E_CHAR && row > 0){
tabula_recta[row][col] = S_CHAR + pos;
pos++;
}
else
tabula_recta[row][col] = S_CHAR+row+col;
}
}
return;
}
/***********************************************
* Function that prints the contents of
* tabula_recta square if you want it.
* *********************************************/
#if 0
void print_tab_recta( char tabula_recta[MAX_ROWS][MAX_COLS])
{
int row , col;
for( row=0; row<MAX_ROWS; row++) {
printf("\n");
for( col=0; col<MAX_COLS; col++){
printf("%c" , tabula_recta[row][col]);
}
}
return;
}
#endif
/********************************************
* vigenere_crypto makes the encryption
* The contents come from tabula_recta square
* it takes the plaintext as argument and the
* key in order to do the encryption procedure
* returns the encrypted string of your msg.
* ******************************************/
char *vigenere_crypto(char *plaintext , char *key)
{
int row_tab_rec , col_tab_rec , i=0;
char *encrypted = plaintext;
while( encrypted[i] ){
row_tab_rec = (key[i] - S_CHAR )%MOD; // For the apropriate row.
col_tab_rec = (plaintext[i] - S_CHAR )%MOD; // For the apropriate column.
encrypted[i] = tabula_recta[row_tab_rec][col_tab_rec]; // The element of the tabula recta square.
i++;
}
return encrypted;
}
/****************************************************
* vigenere_decrypto function makes the decryption
* in order to gve you the plaintext. It takes
* the encrypted msg and the key. It produces the
* decrypted message.
* It returns the decrypted string which is the
* previous plaintext.
* *************************************************/
char *vigenere_decrypto(char *encrypted , char *key)
{
int i=0;
char *decrypted = encrypted;
while( encrypted[i] ) {
if( encrypted[i] >= key[i] )
decrypted[i] = encrypted[i] - (key[i]- S_CHAR)%MOD;
else if ( encrypted[i] < key[i] )
decrypted[i] = E_CHAR + 1 - (key[i] - encrypted[i]) ;
i++;
}
return decrypted;
}
int read_line( char *str , int n)
{
int ch , i=0;
while( isspace( ch = getchar() ))
;
while( ch!= '\n' && ch != EOF) {
if( i < n)
str[i++] = ch;
ch = getchar();
}
str[i] ='\0';
return i;
}
char *key_repeat( char *key , char *plaintext , int KeyLen)
{
char *tmp = calloc( KeyLen + 1, sizeof(char));
int P_Len = strlen(plaintext); // P_Len is the length of your original message.
int i=0;
if( tmp == NULL ){
printf("Error: calloc faild in key_repeat.");
exit(EXIT_FAILURE);
}
strcpy( tmp , key);
if ( KeyLen == P_Len) // same length of key and plaintext.
return key;
// length of key is greater than plaintext.
else if ( KeyLen > P_Len ) {
key[ P_Len ]= '\0';
return key;
}
// length of key is lower than plaintext.
else {
// move the key to null character.
while( *key ){
key++;
plaintext++;
}
// repeat the key in order to be the same in length with plaintext.
while( *plaintext ) {
// if the plaintext has same length with the repeat of the key.
if( P_Len % KeyLen == 0 ) {
strcpy( key , tmp); // repeat the key. Copy the blocks of KeyLen sized.
key += KeyLen; // increase the key to its length.
plaintext += KeyLen;
}
// if the plaintext has no the same length with the repeat of the key.
else if( P_Len % KeyLen != 0 ) {
*key= *tmp; // copy each character.
key++; tmp++; i++; // move the pointers and the counter.
if( i == KeyLen) {
tmp -= KeyLen; i=0; // move back the tmp pointer to the start of key.
}
plaintext++;
}
}
}
free(tmp); // Why here I took an error message?
return key;
}
I have done the checks in the following situations :
- the key has the same length with the plaintext.
- key is greater than plaintext (the lengths)
- key is lower ... and when if the length of the key is divided with the length of the plaintext and or not.
I didn't have problems with the tests. But When I put the free(tmp) into the key_repeat function I had problems... I took a common error sush as :
Code:
*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x09f931f0 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x3de501]
/lib/libc.so.6(+0x6dd70)[0x3dfd70]
....
- What is your opinion about my code?
- What is the problem????
thank you in advance.