//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 /* transpos.c */ /* transposition of rows with columns of an input block */ /* Copyright 1995 Willis E. Howard, III */ /* Willis E. Howard, III email: WEHoward@aol.com mail: POB 1473 Elkhart, IN 46515 */ /* under MSDOS, NMAKE /F TRANSPOS.MAK all clean */ #include #include #include "crypt.h" #include #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_transpos = 0; /* Set to 1 after a valid key has been defined */ static int encrypt_or_decrypt_transpos = ENCRYPTION_SELECT; static char key_string_transpos[257]; /* implementation specific defines */ int rows; int columns; int validate_key(char *); int setblock( void ); int isqrt( unsigned int ); static struct transpose { char data[16384]; int max; int left; char *start; char *next; int count; int row; int column; } trans; /* 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 TRANSPOSITION cipher reads in a block of data,", " exchanges rows and columns, and writes the block out.", " This is repeated for all blocks in the input file.", " Unless a square block is used, the -d option must be", " used for decryption.", "", "KEY", " The key is one or two numbers. If you use more than one", " number and give the key with the -k option on the command", " line, place the phrase within quotes. The first number is", " the number of rows. If a second number is given, it is the", " number of columns. Without a second number, the block will", " have the number of rows and columns given by the first. If", " there is not enough data to fill the block, a smaller block", " size is used. The largest dimensions are 128 rows and 128", " columns. The smallest are 2 rows and 2 columns. If data", " does not completely fill a block, smaller sizes are used.", "", " If a key file exists, only the first line is read, and", " it is used as the key. Use no quotes in the key file.", "", " If there is no key, you will be prompted for one.", NULL } ; char ** crypt_help_transpos() { 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_transpos ( int key_type, char *key_text ) { int i; char *s; FILE *fp; if (key_type == KEY_FILE) /* see if a file name has been given */ { if ((fp=fopen(key_text, "r")) == NULL) { key_defined_transpos = 0; return 0; } s = key_string_transpos; i = 0; for (;;) { *s = fgetc( fp ); if ((*s == '\n') || (*s == EOF)) { *s = '\0'; if (i == 0) { key_defined_transpos = 0; break; } else { key_defined_transpos = validate_key(key_string_transpos); break; } } else if (i == 255) { *++s = '\0'; key_defined_transpos = validate_key(key_string_transpos); 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_transpos; i = 0; for (;;) { *s = fgetc( stdin ); if ((*s == '\n') || (*s == EOF)) { *s = '\0'; if (i == 0) { key_defined_transpos = 0; break; } else { key_defined_transpos = validate_key(key_string_transpos); break; } } else if (i == 255) { *++s = '\0'; key_defined_transpos = validate_key(key_string_transpos); break; } s++; i++; } } else /* copy string up to 256 characters */ { strncpy( key_string_transpos, key_text, 256 ); key_string_transpos[256] = '\0'; key_defined_transpos = validate_key(key_string_transpos); } 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_transpos() { int i; for (i=0; i<257; i++) key_string_transpos[i] = '\0'; rows = 0; columns = 0; key_defined_transpos = 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_transpos( int selection ) { if ( selection == ENCRYPTION_SELECT ) encrypt_or_decrypt_transpos = ENCRYPTION_SELECT; if ( selection == DECRYPTION_SELECT ) encrypt_or_decrypt_transpos = DECRYPTION_SELECT; return encrypt_or_decrypt_transpos; } /* 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_transpos( char *source, char *dest ) { char *s; int c; int iRow; int iCol; FILE *infile; FILE *outfile; qDebug("crypt_key_file: Me ha key_defined_transpos: %d, key_string_transpos:%s", key_defined_transpos,key_string_transpos); qDebug("crypt_key_file: rows: %d, columns:%d", rows,columns); system("pause"); while (!key_defined_transpos) crypt_key_transpos( 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; } if ( encrypt_or_decrypt_transpos == DECRYPTION_SELECT ) { c = rows; rows = columns; columns = c; } trans.max = rows * columns; while (trans.left=fread (trans.data, sizeof (char), trans.max, infile)) { trans.next = trans.data; while (setblock() != 0) for(iCol=0; iCol 128) /* 128 is the largest */ i = 128; rows = i; /* set the row */ while (*s == ' ') /* get rid of spaces */ s++; for (i=0; isdigit(*s); s++) /* get second number */ i = (i * 10) + (int) ((*s) - '0'); if (i == 0) /* no number is OK */ i = rows; /* set columns to rows */ if (i < 3) /* check for minimum */ i = 2; if (i > 128) /* check for maximum */ i = 128; columns = i; /* set the column */ return 1; /* good return code */ } int setblock( void ) { if (trans.left < 4) /* the real easy part */ { trans.start = trans.next; return 0; } if (trans.left == rows*columns) /* the fairly easy part */ { trans.count = trans.left; trans.left = 0; trans.start = trans.next; trans.row = rows; trans.column = columns; return 1; } /* OK, we got here because there was not enough data to fill the rows * columns array. For the rest of the data in the file we have to break it up into smaller parts. The tricky part. */ trans.row = isqrt((unsigned) trans.left); /* guaranteed minimum of 4 bytes */ trans.column = trans.row; trans.start = trans.next; trans.count = trans.column*trans.row; trans.left -= trans.count; trans.next += trans.count; return 1; } /* compute the integer square root of an unsigned integer */ int isqrt(unsigned int input) { union { struct { unsigned int input; unsigned int newbits; } x; long whole; } shift; unsigned int bitcount; unsigned int remainder; unsigned int diff; int result; if (!input) /* 0 is 0 */ return 0; /* just a bit of setup */ bitcount = diff = remainder = result = shift.x.newbits = 0; shift.x.input = input; /* Compute the square root the old fashioned way. Good up to 16 bits in, 8 bits out. The remainder is truncated. */ do /* first skip over those annoying zeroes */ { bitcount++; shift.whole <<= 2; } while (shift.x.newbits == 0); do /* now just like you learned in school, but base 2 */ { remainder = ((remainder - diff) << 2) + shift.x.newbits; diff = ((result << 2) + 1) > remainder ? 0 : (result << 2) + 1; result = (result * 2) + (diff ? 1 : 0); shift.x.newbits = 0; shift.whole <<= 2; } while(bitcount++ < 8); return result; }