/* CCRP.C Encrypt/Decrypt a DOS file */ /* By: Dale Thorn */ /* Version 3.1 */ /* Rev. 29.10.1996 */ #include "stdlib.h" #include "string.h" #include "stdio.h" #include "dos.h" #include "io.h" #include "ccrp.h" V main(I argc, C ** argv) { /* command-line arguments (input file/offset) */ C cmsg[23]; /* initialize the User message string */ U ibit = 0; /* initialize the bit offset in cbuf */ U ibuf = 2048; /* set maximum file buffer length */ U idot; /* initialize the filename extension separator */ I ieof = 0; /* initialize the EOF flag */ U ilen; /* initialize a temporary length variable */ U indx; /* initialize a temporary loop variable */ I iopr; /* initialize the operation code */ U irnd = 0; /* initialize the randomizer seed */ L lbyt; /* initialize the file pointer variable */ L llof; /* initialize the file length variable */ L lrnd = 0; /* initialize the randomizer accumulator */ U _far *uvadr = 0; /* video display pointer */ struct _iobuf *ebuf; /* source file access structure */ C *cbuf = (C *) malloc(2048); /* initialize the file buffer */ C *ctmp = (C *) malloc(2048); /* initialize the temp buffer */ I *int1 = (I *) malloc(3074); /* allocate the sort index array */ I *int2 = (I *) malloc(3074); /* allocate the sort random number array */ I *istk = (I *) malloc(3074); /* allocate the sort stack array */ if (argc == 1) { /* a command line was not supplied */ ifn_msgs("Usage: CCRP(v3.1) filename [/e /d /p /u] [key]", 4, 24, 79, 0, 1); /* display usage message [above] and exit */ } if (argc < 3 || argc > 4) { /* no. of parameters should be one or two */ ifn_msgs("Invalid number of parameters", 4, 24, 79, 1, 1); } /* display no.-of-parameters message [above] and exit */ if (argv[2][0] != '/') { /* slash preceding parameter missing */ ifn_msgs("Invalid operation parameter", 4, 24, 79, 1, 1); } /* display invalid-parameter message [above] and exit */ strupr(argv[1]); /* uppercase the filename */ strupr(argv[2]); /* uppercase the operation code */ if (strchr("DEPU", argv[2][1]) == NULL) { /* invalid parameter */ ifn_msgs("Invalid operation parameter", 4, 24, 79, 1, 1); } /* display invalid-parameter message [above] and exit */ idot = strcspn(argv[1], "."); /* position of filename extension separator */ ilen = strlen(argv[1]); /* length of filename */ if (idot == 0 || idot > 8 || ilen - idot > 4) { /* filename tests bad */ ifn_msgs("Invalid filename", 4, 24, 79, 1, 1); } /* display invalid-filename message [above] and exit */ if (idot < ilen) { /* filename extension separator found! */ if (strcspn(argv[1] + idot + 1, ".") < ilen - idot - 1) { /* 2nd found! */ ifn_msgs("Invalid filename", 4, 24, 79, 1, 1); } /* display invalid-filename message [above] and exit */ } strcpy(cmsg, argv[1]); /* copy filename to message */ strcat(cmsg, " not found"); /* add "not found" to message */ ebuf = fopen(argv[1], "rb+"); /* open the selected file */ llof = filelength(fileno(ebuf)); /* filelength of selected file */ if (ebuf == NULL || llof == -1L || llof == 0) { /* length=0 or call failed */ fclose(ebuf); /* close the file */ remove(argv[1]); /* kill the zero-length file */ ifn_msgs(cmsg, 4, 24, 79, 1, 1); /* display message and exit */ } iopr = argv[2][1] - 68; /* opcode (1=encrypt, 0=decrypt, 12=pad bits) */ if (argc == 4) { /* a seed key was supplied */ ilen = strlen(argv[3]); /* length of optional seed key */ for (indx = 0; indx < ilen; indx++) { /* loop through the seed key */ irnd = argv[3][indx]; /* character at byte position */ switch (indx % 3) { /* select on byte significance */ case 0: /* least significant byte */ lrnd += irnd; /* add to randomizer accum. */ break; case 1: /* 2nd least significant byte */ lrnd += (L) irnd *256; /* add to randomizer accum. */ break; case 2: /* most significant byte */ lrnd += (L) irnd *65536; /* add to randomizer accum. */ break; default: break; } } irnd = (U) (lrnd % 32640) + 1; /* mod randomizer seed to <= 32640 */ } ifn_msgs("Please standby", 4, 24, 79, 0, 0); /* standby message */ if (iopr > 1) { /* operation code is 'P' or 'U' */ ifn_pack(cbuf, llof, ibuf, iopr, ebuf); /* add 8th bits if 7-bit file */ } /* NOTE: ifn_pack does NOT return here */ srand(irnd); /* initialize the random number generator */ for (lbyt = 0; lbyt < llof; lbyt += ibuf) { /* process in ibuf segments */ if (lbyt + ibuf >= llof) { /* current file pointer + ibuf spans EOF */ ibuf = (U) (llof - lbyt); /* reset maximum file buffer length */ ieof = 1; /* set the EOF flag ON */ } ifn_read(cbuf, lbyt, ibuf, ebuf); /* read data into the file buffer */ while (1) { /* loop to process bit groups in cbuf */ ilen = (rand() / 26) + 256; /* buffer seg. bit-len.: 256<=ilen<=1536 */ if (ibit + ilen > ibuf * 8) { /* current bit-pointer+ilen spans cbuf */ if (ieof) { /* EOF flag is ON */ ilen = ibuf * 8 - ibit; /* reset bit-length of buffer segment */ } else { /* EOF flag is OFF; adjust file pointer */ ifn_write(cbuf, lbyt, ibuf, ebuf); /* write data to the file */ lbyt -= (ibuf - ibit / 8); /* set file ptr to reload from ibit */ ibit %= 8; /* set ibit to first byte of cbuf */ break; /* exit loop to reload cbuf from lbyt */ } } /* encrypt or decrypt the current segment [below] */ ifn_cryp(int1, int2, istk, cbuf, ctmp, (I) ibit, ilen, iopr); ibit += ilen; /* increment ibit to next bit-segment */ if (ibit == ibuf * 8) { /* loop until ibit == length of cbuf */ ifn_write(cbuf, lbyt, ibuf, ebuf); /* write data to the file */ ibit = 0; /* set ibit to first byte of cbuf */ break; } } } ifn_msgs("Translation complete", 4, 24, 79, 0, 1); /* disp. message & exit */ } I bitget(C * cstr, I ibit) { /* get a bit-value from a string */ I ival; /* initialize the bit value */ switch (ibit % 8) { /* switch on bit# within character */ case 0: /* bit #0 in target character */ ival = 1; /* value of bit #0 */ break; case 1: /* bit #1 in target character */ ival = 2; /* value of bit #1 */ break; case 2: /* bit #2 in target character */ ival = 4; /* value of bit #2 */ break; case 3: /* bit #3 in target character */ ival = 8; /* value of bit #3 */ break; case 4: /* bit #4 in target character */ ival = 16; /* value of bit #4 */ break; case 5: /* bit #5 in target character */ ival = 32; /* value of bit #5 */ break; case 6: /* bit #6 in target character */ ival = 64; /* value of bit #6 */ break; case 7: /* bit #7 in target character */ ival = 128; /* value of bit #7 */ break; default: break; } return ((cstr[ibit / 8] & ival) != 0); /* return value of target bit */ } V bitput(C * cstr, I ibit, I iput) { /* put a bit-value to a string */ I ival; /* initialize the bit value */ I ipos = ibit / 8; /* position of 8-bit char. in cstr */ switch (ibit % 8) { /* switch on bit# within character */ case 0: /* bit #0 in target character */ ival = 1; /* value of bit #0 */ break; case 1: /* bit #1 in target character */ ival = 2; /* value of bit #1 */ break; case 2: /* bit #2 in target character */ ival = 4; /* value of bit #2 */ break; case 3: /* bit #3 in target character */ ival = 8; /* value of bit #3 */ break; case 4: /* bit #4 in target character */ ival = 16; /* value of bit #4 */ break; case 5: /* bit #5 in target character */ ival = 32; /* value of bit #5 */ break; case 6: /* bit #6 in target character */ ival = 64; /* value of bit #6 */ break; case 7: /* bit #7 in target character */ ival = 128; /* value of bit #7 */ break; default: break; } if (iput) { /* OK to set the bit ON */ if (!(cstr[ipos] & ival)) { /* bit is NOT already ON */ cstr[ipos] += ival; /* set bit ON by adding ival */ } } else { /* OK to set the bit OFF */ if (cstr[ipos] & ival) { /* bit is NOT already OFF */ cstr[ipos] -= ival; /* set bit OFF by subt. ival */ } } } V ifn_cryp(I * int1, I * int2, I * istk, C * cbuf, C * ctmp, I ibit, I ilen, I iopr) { I indx; /* initialize the for-next loop counter */ for (indx = 0; indx < ilen; indx++) { /* loop through ilen array elements */ int1[indx] = indx; /* bit offsets from current ibit offset */ int2[indx] = rand(); /* random number values for sort function */ } ifn_sort(int1, int2, istk, ilen - 1); /* Quicksort by random no. array */ memcpy(ctmp, cbuf, 2048); /* copy data buffer to temp destination buffer */ if (iopr) { /* encrypt operation */ for (indx = 0; indx < ilen; indx++) { /* loop thru ilen array elements */ bitput(ctmp, indx + ibit, bitget(cbuf, int1[indx] + ibit)); /*encrypt */ } } else { /* decrypt operation */ for (indx = 0; indx < ilen; indx++) { /* loop thru ilen array elements */ bitput(ctmp, int1[indx] + ibit, bitget(cbuf, indx + ibit)); /*decrypt */ } } memcpy(cbuf, ctmp, 2048); /* copy temp destination buffer to data buffer */ } V ifn_msgs(C * cmsg, I iofs, I irow, I icol, I ibrp, I iext) { /* display msgs */ io_vcls(7); /* clear the screen */ io_vdsp(cmsg, 4, iofs, 7); /* display the user message */ if (ibrp) { /* OK to sound user-alert (beep) */ printf("\a"); /* sound the user-alert */ } if (iext) { /* OK to exit the program */ io_vcsr(5, 0, 0); /* relocate the cursor */ fcloseall(); /* close all open files */ exit(0); /* return to DOS */ } else { /* do NOT exit the program */ io_vcsr(irow, icol, 0); /* 'hide' the cursor */ } } V ifn_pack(C * cbuf, L llof, U ibuf, I iopr, struct _iobuf *ebuf) { I ibit; /* initialize a temporary loop variable */ U ichr; /* initialize a temporary loop variable */ U incr; /* initialize the bit-pad loop increment */ U itmp = ibuf; /* make a copy of the file buffer length */ L lbyt; /* initialize the file pointer variable */ L lcnt = 0; /* initialize the current total one-bits */ L ltmp; /* initialize a copy of current total one-bits */ L ltot; /* initialize the no. of 8th bits to set ON */ for (lbyt = 0; lbyt < llof; lbyt += itmp) { /* process in itmp segments */ if (lbyt + itmp > llof) { /* current file pointer + itmp spans EOF */ itmp = (U) (llof - lbyt); /* reset maximum file buffer length */ } ifn_read(cbuf, lbyt, itmp, ebuf); /* read data into the file buffer */ if (iopr == 17) { /* opcode == unpad bits */ for (ichr = 0; ichr < itmp; ichr++) { /* process bytes in cbuf */ bitput(cbuf, ichr * 8 + 7, 0); /* set each 8th bit OFF */ } ifn_write(cbuf, lbyt, itmp, ebuf); /* save current buffer to file */ } else { /* opcode == pad bits - validation pass */ for (ichr = 0; ichr < itmp; ichr++) { /* process bytes in cbuf */ for (ibit = 0; ibit < 8; ibit++) { /* process bits in cbuf */ lcnt += bitget(cbuf, ichr * 8 + ibit); /* add 0/1 bit to total */ if (ibit == 7) { /* this is the 8th bit of ichr */ if (bitget(cbuf, ichr * 8 + ibit)) { /* the 8th bit is ON */ ifn_msgs("8th bit(s) are ON - can't do bit-pad", 4, 24, 79, 1, 1); } /* can't add bits - display message (above) and exit */ } } } } } if (iopr == 17) { /* opcode == unpad bits */ ifn_msgs("Bit-unpadding complete", 4, 24, 79, 0, 1); /* message & exit */ } ltot = llof * 4 - lcnt; /* set ltot as the no. of 8th bits to set ON */ if (ltot > 0) { /* one-bits < zero bits; commence padding */ if (ltot > llof) { /* one-bits required exceed total bytes */ ltot = llof; /* reset one-bits to equal total bytes */ } itmp = ibuf; /* reset the copy of the file buffer length */ ltmp = ltot; /* make a copy of the 8th bits to set ON */ for (lbyt = 0; lbyt < llof; lbyt += itmp) { /* process in itmp segments */ if (lbyt + itmp > llof) { /* current file pointer + itmp spans EOF */ itmp = (U) (llof - lbyt); /* reset maximum file buffer length */ } ifn_read(cbuf, lbyt, itmp, ebuf); /* read data into the file buffer */ incr = (U) ((llof - lbyt) / ltmp); /* set the bit-pad loop increment */ for (ichr = 0; ichr < itmp; ichr += incr) { /* loop to set 8th bits */ bitput(cbuf, ichr * 8 + 7, 1); /* set each 8th bit ON */ ltmp--; /* decrement the total one-bits padded */ if (ltmp == 0) { /* all 8th bits are now set ON */ break; /* all 8th bits are ON - exit ichr loop */ } } ifn_write(cbuf, lbyt, itmp, ebuf); /* save current buffer to file */ if (ltmp == 0) { /* all 8th bits are now set ON */ break; /* all 8th bits are ON - exit lbyt loop */ } } ifn_msgs("Bit-padding complete", 4, 24, 79, 0, 0); /* disp.message only */ } else { /* one-bits >= zero bits; padding not needed */ ifn_msgs("Bit-padding not needed", 4, 24, 79, 1, 0); /* disp.msg.& exit */ ltot = 0; /* reset one-bits required for below message */ } io_vcsr(6, 0, 0); /* relocate the cursor */ printf("%s%ld", "Total bits in source: ", llof * 8); /* total bits in file */ io_vcsr(8, 0, 0); /* relocate the cursor */ printf("%s%ld", "Total one-bits begin: ", lcnt); /* one-bits before pad */ io_vcsr(10, 0, 0); /* relocate the cursor */ printf("%s%ld\n", "Total one-bits added: ", ltot); /* no. one-bits added */ fcloseall(); /* close all open files */ exit(0); /* return to DOS */ } V ifn_sort(I * int1, I * int2, I * istk, I imax) { /* array Quicksort function */ I iext; /* initialize the outer-loop exit flag */ I ilow; /* initialize the low array pointer */ I irdx = 0; /* initialize the sort radix */ I isp1; /* initialize the low stack pointer */ I isp2; /* initialize the top stack pointer */ I itop; /* initialize the top array pointer */ I iva1; /* initialize array value from low stack pointer */ I iva2; /* initialize array value from low stack pointer */ istk[0] = 0; /* initialize the low array pointer */ istk[1] = imax; /* initialize the top array pointer */ while (irdx >= 0) { /* loop until sort radix < 0 */ isp1 = istk[irdx + irdx]; /* set the low stack pointer */ isp2 = istk[irdx + irdx + 1]; /* set the top stack pointer */ irdx--; /* decrement the sort radix */ iva1 = int1[isp1]; /* get array value from low stack pointer */ iva2 = int2[isp1]; /* get array value from low stack pointer */ itop = isp2 + 1; /* set the top array pointer */ ilow = isp1; /* set the low array pointer */ while (1) { /* loop to sort within the radix limit */ itop--; /* decrement the top array pointer */ if (itop == ilow) { /* top array pointer==low array pointer */ break; /* skip to next radix value */ } if (iva2 > int2[itop]) { /* value @low pointer>value @top pointer */ int1[ilow] = int1[itop]; /* swap low and top array values */ int2[ilow] = int2[itop]; /* swap low and top array values */ iext = 0; /* initialize outer-loop exit flag */ while (1) { /* loop to compare and swap array values */ ilow++; /* increment the low array pointer */ if (itop == ilow) { /* top array pointer==low array pointer */ iext = 1; /* set outer-loop exit flag ON */ break; /* skip to next radix value */ } if (iva2 < int2[ilow]) { /* value @low ptr. 1) { /* low segment-width is > 1 */ irdx++; /* increment the sort radix */ istk[irdx + irdx] = ilow + 1; /* reset low array pointer */ istk[irdx + irdx + 1] = isp2; /* reset top array pointer */ } if (itop - isp1 > 1) { /* top segment-width is > 1 */ irdx++; /* increment the sort radix */ istk[irdx + irdx] = isp1; /* reset low array pointer */ istk[irdx + irdx + 1] = itop - 1; /* reset top array pointer */ } } } V ifn_read(C * cbuf, L lbyt, U ibuf, struct _iobuf *ebuf) { /* read f/binary */ fseek(ebuf, lbyt, SEEK_SET); /* set the buffer-read pointer */ fread((V *) cbuf, 1, ibuf, ebuf); /* read data from the binary file */ } V ifn_write(C * cbuf, L lbyt, U ibuf, struct _iobuf *ebuf) { /* write t/binary */ fseek(ebuf, lbyt, SEEK_SET); /* set the buffer-write pointer */ fwrite((V *) cbuf, 1, ibuf, ebuf); /* write data to the binary file */ } U io_vadr(I inop) { /* get video address (color or b/w) */ rg.h.ah = 15; /* video-address function */ int86(0x10, &rg, &rg); /* call DOS for video address */ if (rg.h.al == 7) { /* register A-low is 7 */ return (0xb000); /* return b/w address */ } else { /* register A-low is NOT 7 */ return (0xb800); /* return color address */ } } V io_vcls(I iclr) { /* clear screen function */ I irow; /* initialize the row number variable */ C cdat[81]; /* initialize the row data buffer */ memset(cdat, ' ', 80); /* clear the row data buffer */ cdat[80] = '\0'; /* terminate the row data buffer */ for (irow = 0; irow < 25; irow++) { /* loop thru the screen rows */ io_vdsp(cdat, irow, 0, iclr); /* display each screen row */ } } V io_vcsr(I irow, I icol, I icsr) { /* set cursor position [and size] */ rg.h.ah = 2; /* cursor-position function */ rg.h.bh = 0; /* video page zero */ rg.h.dh = (C) irow; /* row number */ rg.h.dl = (C) icol; /* column number */ int86(0x10, &rg, &rg); /* call DOS to position cursor */ if (icsr) { /* cursor-size specified */ rg.h.ah = 1; /* cursor-size function */ rg.h.ch = (C) (13 - icsr); /* set cursor-begin line */ rg.h.cl = 12; /* set cursor-end line */ int86(0x10, &rg, &rg); /* call DOS to set cursor size */ } } V io_vdsp(C * cdat, I irow, I icol, I iclr) { /* display data on screen */ I ilen = strlen(cdat); /* length of string to be displayed */ I iptr; /* byte-counter for displayed string */ U uclr = iclr * 256; /* unsigned attribute high-byte value */ if (!uvadr) { /* video pointer segment not set */ FP_SEG(uvadr) = io_vadr(0); /* set video pointer segment */ } FP_OFF(uvadr) = irow * 160 + icol * 2; /* set video pointer offset */ for (iptr = 0; iptr < ilen; iptr++) { /* loop thru displayed string */ *uvadr = uclr + (UC) cdat[iptr]; /* put data to video memory */ uvadr++; /* increment video display pointer */ } }