home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
POINT Software Programming
/
PPROG1.ISO
/
c
/
snippets
/
hi-crypt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
6KB
|
251 lines
/*
** HI-CRYPT.C - Enhanced security S-CODER file encryptor/decryptor
**
** public domain demo by Bob Stout
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
** Globals & prototypes from CRYPT.C, also in SNIPPETS
*/
extern char *cryptext;
extern int crypt_length, crypt_ptr;
void crypt(unsigned char *);
void bufcrypt(unsigned char *buf, long length);
/*
** Other SNIPPETS prototypes from CRC-16.C and CANT.C
*/
unsigned short crc16(char *, unsigned short);
FILE *cant(char *, char *);
/*
** HI-CRYPT.C globals and prototypes
*/
int cryptqual(void); /* Qualify the key */
void setup(void); /* Set hide_loc, hide_ix, crypt_ptr */
void shuffle(void); /* Assymetrical block transposition */
void encrypt(void); /* Encrypt a file */
void decrypt(void); /* Decrypt a file */
void usage(void); /* Tell 'm how it works! */
long hide_loc; /* Where we save the file length */
unsigned hide_ix;
FILE *infile, *outfile;
union { /* Transposition cipher block */
char in[16384];
char proc[256][64];
char out[64][256];
} buf;
union { /* Size of the plain text file */
long len;
unsigned char blen[4];
} fsize;
/*
** GO - Collect $200...
*/
main(int argc, char *argv[])
{
if (5 > argc || NULL == strchr("EeDd", argv[1][0]))
usage();
infile = cant(argv[3], "rb");
outfile = cant(argv[4], "w+b");
cryptext = argv[2];
crypt_length = strlen(cryptext);
if (cryptqual())
{
puts("\aHI-CRYPT: Key is not sufficiently complex");
return EXIT_FAILURE;
}
if (strchr("Ee", argv[1][0]))
encrypt();
else decrypt();
fclose(infile);
fclose(outfile);
return EXIT_SUCCESS;
}
/*
** They goofed - tell 'em how it works!
*/
void usage(void)
{
puts("\aUsage: HI-CRYPT { E | D } key input_file output_file");
puts("where: E = Encrypt");
puts(" D = Decrypt");
puts("NOTE : If the key contains spaces, it must be enclosed "
"in quotation marks");
exit(EXIT_FAILURE);
}
/*
** The key must be 64 bits or more and contain at least 5 distinct chars
*/
int cryptqual(void)
{
int i, j = 0;
static char found[6];
memset(found, 0, 6);
if (8 > crypt_length)
return -1;
for (i = 0; i < crypt_length; ++i)
{
if (strchr(found, cryptext[i]))
continue;
found[j++] = cryptext[i];
if (5 < j)
return 0;
}
return -1;
}
/*
** Scramble transposition block buffer
*/
void shuffle(void)
{
int i;
static char buf2[16384];
char *p = buf2;
for (i = 0; i < 64; ++i)
{
memcpy(p, buf.out[63 - i], 256);
p = &p[256];
}
memcpy(buf.in, buf2, 16384);
}
/*
** Compute the location to save the file size
*/
void setup(void)
{
unsigned short crc;
crc = crc16(cryptext, crypt_length);
hide_ix = crc % (16384 - sizeof(long));
hide_loc = (long)(sizeof(long) + hide_ix);
crypt_ptr = crc % crypt_length;
srand(hide_ix);
}
/*
** Encrypt a file
*/
void encrypt(void)
{
unsigned i, j, n;
long swap1, swap2;
/*
** Get the file size
*/
setup();
fseek(infile, 0L, SEEK_END);
fsize.len = ftell(infile);
rewind(infile);
/*
** Encrypt & save the file size
*/
for (i = 0; i < sizeof(long); ++i)
crypt(&fsize.blen[i]);
fwrite(&fsize.len, sizeof(long), 1, outfile);
/*
** Encrypt the plaintext
*/
while (0 != (n = fread(buf.in, 1, 16384, infile)))
{
while (16384 > n)
buf.in[n++] = rand();
for (i = 0; i < 64; ++i)
{
for (j = 0; j < 256; ++j)
crypt(&buf.proc[j][63 - i]);
}
shuffle();
fwrite(buf.in, 1, 16384, outfile);
}
/*
** Relocate the file size
*/
fseek(outfile, hide_loc, SEEK_SET);
fread(&swap2, sizeof(long), 1, outfile);
rewind(outfile);
fread(&swap1, sizeof(long), 1, outfile);
fseek(outfile, hide_loc, SEEK_SET);
fwrite(&swap1, sizeof(long), 1, outfile);
rewind(outfile);
fwrite(&swap2, sizeof(long), 1, outfile);
}
/*
** Decrypt a file
*/
void decrypt(void)
{
unsigned i, j, n;
int block_1 = -1;
long hide_buf;
/*
** Retrieve & decrypt the file size
*/
setup();
fseek(infile, hide_loc, SEEK_SET);
fread(&fsize.len, sizeof(long), 1, infile);
rewind(infile);
fread(&hide_buf, sizeof(long), 1, infile);
for (i = 0; i < sizeof(long); ++i)
crypt(&fsize.blen[i]);
/*
** Decrypt the ciphertext
*/
while (0 != (n = fread(buf.in, 1, 16384, infile)))
{
if (block_1)
{
block_1 = 0;
memcpy(&buf.in[hide_ix], &hide_buf, sizeof(long));
}
shuffle();
for (i = 0; i < 64; ++i)
{
for (j = 0; j < 256; ++j)
crypt(&buf.proc[j][63 - i]);
}
if (16384 <= fsize.len)
fwrite(buf.in, 1, 16384, outfile);
else fwrite(buf.in, 1, fsize.len, outfile);
fsize.len -= n;
}
}