//This program is free software: you can redistribute it and/or modify it under the terms #of the GNU General Public License as published by the Free Software Foundation, either #version 3 of the License, or (at your option) any later version.
//This program is distributed in the hope that it will be useful, but WITHOUT ANY #WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A #PARTICULAR PURPOSE. See the GNU General Public License for more details.
//You should have received a copy of the GNU General Public License along with this #program. If not, see
/* vigenere.c */
/* Classical Vigenere cipher */
/* Taken from B. Schneier's sample program in Applied Cryptography */
/* Unless otherwise noted Copyright 1995 Willis E. Howard, III */
/* Willis E. Howard, III email: WEHoward@aol.com mail: POB 1473 Elkhart, IN 46515 */
/* under MSDOS, NMAKE /F VIGENERE.MAK all clean */
#include
#include
#include "crypt.h"
#include "vigenere.h"
#include
#include
#include
/*
This routine uses the common interface to CRYPT.C.
Generally, the name of this module becomes the name
of the executable file.
*/
static int key_defined_vigenere = 1; /* Set to 1 after a valid key has been defined */
static int encrypt_or_decrypt_vigenere = ENCRYPTION_SELECT;
static char key_string_vigenere[257];
/* Special defines for this module only */
/* number of letters in the alphabet */
#define ALPHA_LEN 26
/*
A more true VIGENERE cipher maps everything to upper case.
To achieve that, set SAVE_CASE to 0 and use an upper case
only encryption/decryption key. The origial cipher also
jumbles spaces between words. This version retains all word
lengths and non-alphabetical characters, allowing a true
reconstruction of the original text with the VIGENERE cipher.
*/
#define SAVE_CASE (1)
/*
cipher_doc:
This array of strings must have two sections:
CIPHER that describes the cipher used and
KEY that describes how the key is defined and entered.
*/
static char *cipher_doc[]=
{
"CIPHER",
" The VIGENERE cipher is a polyalphabetic substitution cipher.",
" One letter of the key is used to encrypt one letter of text.",
" As letters of the key are used up, the key is reused. To",
" decrypt the encrypted text, use the -d option and the same key.",
" This version retains character case.",
"",
" This cipher is mostly for historical interest. It was used",
" during the American Civil War, and has recently been used in",
" WordPerfect encryption.",
"",
"KEY",
" The key is an ASCII string of alphabetic characters.",
" Using non-alphabetical key characters may corrupt the text.",
" At most 256 characters will be used in the phrase.",
"",
" If a key file exists, only the first line is read, and",
" it is used as the key phrase.",
"",
" If there is no key phrase, you will be prompted for one.",
NULL
} ;
char ** crypt_help_vigenere()
{
return cipher_doc; /* return a pointer to the help strings */
}
/*
crypt_key:
Get the key from the passed string (that may be a file name in some
implementations) or from a key file name. Return 0 on success but
exit on error.
*/
int
crypt_key_vigenere ( int key_type, char *key_text )
{
int i;
char *s;
FILE *fp;
if (key_type == KEY_FILE) /* a file name has been given */
{
if ((fp=fopen(key_text, "r")) == NULL)
{
key_defined_vigenere = 0;
return 0;
}
s = key_string_vigenere;
i = 0;
for (;;)
{
*s = fgetc( fp );
if ((*s == '\n') || (*s == EOF))
{
*s = '\0';
if (i == 0)
{
key_defined_vigenere = 0;
break;
}
else
{
key_defined_vigenere = 1;
break;
}
}
else if (i == 255)
{
*++s = '\0';
key_defined_vigenere= 1;
break;
}
s++;
i++;
}
fclose( fp );
return 0;
}
else if (key_type == KEY_IMMEDIATE) /* a key string has been given */
{
if (!strcmp( key_text, "?" )) /* prompt for key */
{
printf("Key: "); /* input key from stdin */
s = key_string_vigenere;
i = 0;
for (;;)
{
*s = fgetc( stdin );
if ((*s == '\n') || (*s == EOF))
{
*s = '\0';
if (i == 0)
{
key_defined_vigenere = 0;
break;
}
else
{
key_defined_vigenere = 1;
break;
}
}
else if (i == 255)
{
*++s = '\0';
key_defined_vigenere = 1;
break;
}
s++;
i++;
}
}
else /* copy string up to 256 characters */
{
strncpy( key_string_vigenere, key_text, 256 );
key_string_vigenere[256] = '\0';
key_defined_vigenere = 1;
}
return 0;
}
fprintf( stderr, "Error getting key\n" );
exit( 1 );
}
/*
crypt_key_erase:
If a local copy of the key has been made, erase it from memory.
This increases security that the key can not be obtained from
an examination of memory.
*/
void
crypt_key_erase_vigenere()
{
int i;
for (i=0; i<257; i++)
key_string_vigenere[i] = '\0';
key_defined_vigenere = 0;
return;
}
/*
crypt_select:
If encryption and decryption require different ciphers,
this routine defines the direction. Valid choices are
ENCRYPTION_SELECT and DECRYPTION_SELECT.
*/
int
crypt_select_vigenere( int selection )
{
if ( selection == ENCRYPTION_SELECT )
encrypt_or_decrypt_vigenere = ENCRYPTION_SELECT;
if ( selection == DECRYPTION_SELECT )
encrypt_or_decrypt_vigenere = DECRYPTION_SELECT;
return encrypt_or_decrypt_vigenere;
}
/*
crypt_file:
encrypt or decrypt the source to the destination file.
Do not exit from this routine. Return 0 on success
and return 1 on error. Use an fprintf(stderr, ... ) to
report the nature of the error and close any open files.
This allows the main routine to do some cleanup before
exiting.
*/
int
crypt_file_vigenere( char *source, char *dest )
{
char *s;
char case_char;
int c;
FILE *infile;
FILE *outfile;
while (!key_defined_vigenere)
crypt_key_vigenere( KEY_IMMEDIATE, "?" );
if ((infile = fopen( source, "rb" )) == NULL)
{
fprintf( stderr, "Can not open %s for reading.\n", source);
return 1;
}
if ((outfile = fopen( dest, "wb" )) == NULL)
{
fprintf( stderr, "Can not open %s for writing.\n", dest);
fclose( infile );
return 1;
}
s = key_string_vigenere;
while ( (c = fgetc( infile )) != EOF )
{
if ( !*s )
s = key_string_vigenere;
if (isalpha(c))
{
if (SAVE_CASE)
case_char = c;
else
case_char = *s;
c = toupper(c) - 'A';
if ( encrypt_or_decrypt_vigenere == ENCRYPTION_SELECT )
c = (c + (toupper(*s) - 'A')) % ALPHA_LEN;
else
c = (c + ALPHA_LEN - (toupper(*s) - 'A')) % ALPHA_LEN;
c = c + (isupper(case_char) ? 'A' : 'a');
}
if ( fputc( c, outfile ) == EOF )
{
fprintf( stderr, "Could not write to output file %s\n", dest );
fclose( infile );
fclose( outfile );
return 1;
}
s++;
}
fclose( infile );
fclose( outfile );
return 0;
}