home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / Dloads / UTILITIE / TANGLE30.ZIP / TANGLE.C < prev    next >
C/C++ Source or Header  |  1990-05-09  |  10KB  |  261 lines

  1. /***********************************************************************/
  2. /* (c) Copyright 1989, 1990, Alan Finlay.      Tangle, Version 3.0 .    */
  3. /* This program is intended for Public Domain, and may not be sold or    */
  4. /* marketed in any form without the permission and written consent of     */
  5. /* the author.  I retain all copyrights to this program, in either the    */
  6. /* original or modified forms, and no violation, deletion, or change of   */
  7. /* the copyright notice is allowed.  Every effort has been made to ensure */
  8. /* this product provides a secure encryption system.  Mistakes can be     */
  9. /* made however both in the theoretical basis and implementation of such  */
  10. /* a system.  See the associated documentation for a discussion of known  */
  11. /* limitations.  The source code has been provided so you can inspect it  */
  12. /* and use it at your own risk.  I will accept no responsibility for any  */
  13. /* loss, damage, or compromised data caused directly or indirectly by     */
  14. /* this program.  It is released on an "as is" basis with no warranty    */
  15. /* as to its being fit or suitable for encrypting any form of data.     */
  16. /***********************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <dos.h>
  20. #include <sys\stat.h>
  21.  
  22. #define ENCRYPT 1        /* Choose tangle (1) or untangle (0) */
  23. #define DEBUG 0          /* Show page after each shuffle if non zero */
  24. #define TRUE -1
  25. #define FALSE 0
  26. #define LIMIT 100        /* Maximum block size is LIMIT*LIMIT */
  27. #define SECURE 10        /* The number of block transformations */
  28. #define MINB 450         /* Minimum block size - insecure if too small */
  29.  
  30. typedef unsigned char line[LIMIT];
  31.  
  32. char copyright[40] = "(c) copyright 1989,1990, Alan Finlay";
  33.  
  34. unpat(page,wide,high) /* Simple substitution to eliminate simple patterns */
  35.    line page[LIMIT];  /* [width,height] */
  36.    int wide,high;
  37.    {
  38.    int i,j,k;
  39.    k = 0;
  40.    for (i=0;i<wide;i++) for (j=0;j<high;j++) {
  41.       k = (k+7)%256;
  42.       page[i][j] = page[i][j] ^ k;
  43.       }
  44.    }
  45.  
  46. #if ENCRYPT
  47. shuffle(page1,code,wide,high)
  48.    line page1[LIMIT];  /* [width,height] */
  49.    line code;
  50.    int wide,high;
  51.    {
  52.    int i,j,k,key,shift;
  53.    line *mix1,*mix2;
  54.    line *oldline,page2[LIMIT];  /* [height,width] */
  55.    for (k=0;k<SECURE;k++) { /* See mixup below (2 security phases) */
  56. #if DEBUG
  57.       show(page1,wide,high);
  58. #endif
  59.       /* Shift columns */
  60.       for (i=0;i<wide;i++) {
  61.          oldline = page1[i];
  62.          key = (int) code[i];
  63.          for (j=0;j<high;j++) page2[j][i] =(*oldline)[(j+key)%high];
  64.          }
  65.       /* Mixup */
  66.          for (j=1;j<high;j+=2) {
  67.          mix1 = page2[j-1];
  68.          mix2 = page2[j];
  69.          for (i=0;i<wide;i++) (*mix2)[i] = ((*mix2)[i]^(*mix1)[i])+1;
  70.                /* Assume overflow ignored so 255+1==0 */
  71.          }
  72.       /* Shift rows */
  73.       for (j=0;j<high;j++) {
  74.          oldline = page2[j];
  75.          shift = (j%(wide-1))+1;
  76.          for (i=0;i<wide;i++) page1[i][j] = (*oldline)[(i+shift)%wide];
  77.          }
  78.       /* Eliminate any pattern (after first iteration only) */
  79.       if (k==0) unpat(page1,wide,high);
  80.       }
  81.    }
  82.  
  83. #else
  84. unshuffle(page1,code,wide,high)
  85.    line page1[LIMIT];  /* [width,height] */
  86.    line code;
  87.    int wide,high;
  88.    {
  89.    int i,j,k,key,shift;
  90.    line *mix1,*mix2;
  91.    line *newline,page2[LIMIT];  /* [height,width] */
  92.    for (k=0;k<SECURE;k++) {  /* Check this times 2 as in shuffle */
  93. #if DEBUG
  94.       show(page1,wide,high);
  95. #endif
  96.       /* Eliminate any pattern (before last iteration only) */
  97.       if (k==SECURE-1) unpat(page1,wide,high);
  98.       /* Shift rows back */
  99.       for (j=0;j<high;j++) {
  100.          newline = page2[j];
  101.          shift = wide-(j%(wide-1))-1;
  102.          for (i=0;i<wide;i++) (*newline)[i] = page1[(i+shift)%wide][j];
  103.          }
  104.       /* Reverse mixup */
  105.       for (j=1;j<high;j+=2) {
  106.          mix1 = page2[j-1];
  107.          mix2 = page2[j];
  108.          for (i=0;i<wide;i++) (*mix2)[i] = ((*mix2)[i]-1)^(*mix1)[i];
  109.                 /*  Assume underflow is ignored so 0-1==255 */
  110.          }
  111.       /* Shift columns back */
  112.       for (i=0;i<wide;i++) {
  113.          newline = page1[i];
  114.          key = (int) code[i];
  115.          for (j=0;j<high;j++) (*newline)[(j+key)%high] = page2[j][i];
  116.          }
  117.       }
  118.    }
  119. #endif
  120.  
  121. show(page,wide,high)
  122.    line page[LIMIT];
  123.    int wide,high;
  124.    {
  125.    int i,j;
  126.    puts("\n");
  127.    for (j=0;j<high;j++) {
  128.       putc('\n',stdout);
  129.       for (i=0;i<wide;i++) {
  130.          if (page[i][j]<30) putc('*',stdout);
  131.          else putc(page[i][j],stdout);
  132.          }
  133.       }
  134.    }
  135.  
  136. main (argc,argv)
  137.    int argc;
  138.    char *argv[];
  139. {
  140.    FILE *infile,*outfile;
  141.    int wide,high,i,j,k;    /* Block width and height, loop counters */
  142.    int blkn = 1;           /* Block counter */
  143.    int clen;        /* Password code length */
  144.    long chksum;     /* Password checksum */
  145.    int ch = 0;
  146.    int invers;             /* Version of input file for decrypt */
  147.    int vers = 3;           /* Version of this program */
  148.    line page[LIMIT],code;
  149. #if ENCRYPT
  150.    int chrcnt;       /* Character counter */
  151.    long fsize;       /* Input file size */
  152.    int blocksize,nblocks;
  153.    struct time t;  /* For system time */
  154.    struct stat st; /* For input file stats */
  155.    /* Randomise the rand() function */
  156.    gettime(&t);
  157.    srand(t.ti_min*400+t.ti_sec*100+t.ti_hund); /* random seed <30000 */
  158.    /* Check the input arguments */
  159.    if (argc!=3) {puts("\nUsage is: tangle src dst\n"); exit(1);}
  160. #else
  161.    int blkcnt;
  162.    /* Check the input arguments */
  163.    if (argc!=3) {puts("\nUsage is: untangle src dst\n"); exit(1);}
  164. #endif
  165.    if ((infile = fopen(argv[1],"rb")) == NULL) {
  166.       printf("\n%s",argv[1]); perror(" "); exit(1);}
  167.    if ((outfile = fopen(argv[2],"wb")) == NULL) {
  168.       printf("\n%s",argv[2]); perror(" "); exit(1);}
  169. #if ENCRYPT
  170.    /* Get input file size */
  171.    if (stat(argv[1],&st)!=0) {perror(" "); exit(1);}
  172.    fsize = st.st_size;
  173.    printf("The input file size is %ld\n",fsize);
  174.    /* Choose block size accordingly */
  175.    if (fsize<(LIMIT*LIMIT)) blocksize = (int) fsize;
  176.    else {
  177.       nblocks = (int) (fsize/(LIMIT*LIMIT)+1);
  178.       blocksize = (int) (fsize/nblocks+1);
  179.       }
  180.    if (fsize<MINB) blocksize = MINB;    /* Minimum block size enforced */
  181.    wide = 0; while (wide*wide<blocksize) wide++;  /* Approx square root */
  182.    wide = wide+10; if (wide>LIMIT) wide = LIMIT;
  183.    high = blocksize/wide+1; if (high>LIMIT) high = LIMIT;
  184.    while (1) {
  185.       blocksize = wide*high;
  186.       if (fsize<(long) blocksize) break;
  187.       else {
  188.          /* Multiple blocks, check for last block too small */
  189.          if (((fsize-1)%blocksize)>(blocksize*3/4)) break;
  190.          /* (fsize-1) is used above so perfect fit is accepted! */
  191.          high--; wide--; /* Try a smaller block */
  192.          }
  193.       if (wide<50) break;
  194.       }
  195.    printf("The width and height are (%d,%d)\n",wide,high);
  196.    printf("The last block is %ld bytes\n",((fsize-1)%blocksize)+1);
  197.    fprintf(outfile,"%d,%d,%d,",vers,wide,high);
  198. #else
  199.    fscanf(infile,"%d,%d,%d,",&invers,&wide,&high);
  200.    if (invers!=vers) {
  201.       printf("This is version %d of the encryption program.\n",vers);
  202.       printf("The input file is for program version %d or invalid.\n",invers);
  203.       exit(1);
  204.       }
  205. #endif
  206.    /* Get password */
  207.    while(1) {
  208.       puts("\nPlease enter your password");
  209.       fgets(code,LIMIT,stdin);
  210.       clen = strlen(code);
  211.       if (clen>9) break;
  212.       puts("Insecure password, try a longer one.");
  213.       puts("For security do not use a name or word in any dictionary.");
  214.       puts("For example use something like \"Dazed and Konfuzed\"");
  215.       }
  216.    for (i=0;i<25;i++) puts(" ");   /* Clear the screen */
  217.    if (clen>wide) puts("Warning: tail of password ignored");
  218.    /* Extend password to possible limit, not null terminated */
  219.    for (i=clen;i<LIMIT;i++) code[i] = code[i%clen] ^ '\152';
  220.    /* Generate a checksum for the characters */
  221.    for (chksum=0,i=0;i<clen;i++) chksum += (int) code[i]*i;
  222.    printf("The password checksum is %ld.  Please wait ...\n",chksum % 1000);
  223.    do { /* tangle or untangle a block */
  224. #if ENCRYPT
  225.       chrcnt = 0;
  226. #else
  227.       if (fscanf(infile,"%d,",&blkcnt)==EOF) goto NOBLOCK;
  228. #endif
  229.       for (j=0;j<high;j++) {
  230.          for (i=0;i<wide;i++) {
  231.             if ((ch = getc(infile)) != EOF) {
  232.                page[i][j] = ch;
  233. #if ENCRYPT
  234.                chrcnt++;}
  235.             else if (i==0 && j==0) goto NOBLOCK; /* EOF at start of block! */
  236.             /* Pad the last block with existing junk */
  237.             else page[i][j] = page[rand()%wide][rand()%high];
  238. #else
  239.                ;}
  240.             else {puts("Error: unexpected end of file"); goto NOBLOCK;}
  241. #endif
  242.             }
  243.          }
  244. #if ENCRYPT
  245.       fprintf(outfile,"%d,",chrcnt);
  246.       shuffle(page,code,wide,high);
  247.       for (j=0;j<high;j++) for (i=0;i<wide;i++) putc(page[i][j],outfile);
  248. #else
  249.       unshuffle(page,code,wide,high);
  250.       for (j=0;j<high;j++) for (i=0;i<wide;i++)
  251.          if ((j*wide+i)<blkcnt) putc(page[i][j],outfile);
  252. #endif
  253.       printf("Finished block number %d\n",blkn++);
  254.       }
  255.    while (ch != EOF);
  256. NOBLOCK:                  /* Jump here to avoid writing an empty block */
  257.    for (i=0;i<LIMIT;i++) code[i] = ' ';   /* Rubout the password before exit */
  258.    fclose(infile);
  259.    fclose(outfile);
  260. }
  261.