home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / crypt / diverse / tangle < prev   
Encoding:
Text File  |  1991-06-28  |  10.3 KB  |  300 lines

  1. /***********************************************************************/
  2. /* (c) Copyright 1989, 1990, Alan Finlay.      Tangle, Version 3.2 .    */
  3. /* This program may be freely distributed but 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.  I will accept no responsibility for  */
  8. /* any loss, damage, or compromised data caused directly or indirectly by */
  9. /* this program.  It is released on an "as is" basis with no warranty    */
  10. /* as to its being fit or suitable for encrypting any form of data.     */
  11. /***********************************************************************/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <dos.h>
  15. #include <sys\stat.h>
  16.  
  17. #define ENCRYPT 1        /* Choose tangle (1) or untangle (0) */
  18. #define DEBUG 0          /* Show page after each shuffle if non zero */
  19. #define TRUE -1
  20. #define FALSE 0
  21. #define LIMIT 100        /* Maximum block size is LIMIT*LIMIT */
  22. #define SECURE 10        /* The number of block transformations */
  23. #define MINB 450         /* Minimum block size - insecure if too small */
  24.  
  25. typedef unsigned char line[LIMIT];
  26.  
  27. char copyright[40] = "(c) copyright 1989,1990, Alan Finlay";
  28.  
  29. unpat(page,wide,high) /* Simple substitution to eliminate simple patterns */
  30.    line page[LIMIT];  /* [width,height] */
  31.    int wide,high;
  32.    {
  33.    int i,j,k;
  34.    k = 0;
  35.    for (i=0;i<wide;i++) for (j=0;j<high;j++) {
  36.       k = (k+7)%256;
  37.       page[i][j] = page[i][j] ^ k;
  38.       }
  39.    }
  40.  
  41. #if ENCRYPT
  42. shuffle(page1,code,wide,high)
  43.    line page1[LIMIT];  /* [width,height] */
  44.    line code;
  45.    int wide,high;
  46.    {
  47.    int i,j,k,key,shift;
  48.    line *mix1,*mix2;
  49.    line *oldline,page2[LIMIT];  /* [height,width] */
  50.    for (k=0;k<SECURE;k++) {
  51. #if DEBUG
  52.       show(page1,wide,high);
  53. #endif
  54.       /* Shift columns */
  55.       for (i=0;i<wide;i++) {
  56.          oldline = page1[i];
  57.          key = (int) code[i];
  58.          for (j=0;j<high;j++) page2[j][i] =(*oldline)[(j+key)%high];
  59.          }
  60.       /* Mixup */
  61.          for (j=1;j<high;j+=2) {
  62.          mix1 = page2[j-1];
  63.          mix2 = page2[j];
  64.          for (i=0;i<wide;i++) (*mix2)[i] = ((*mix2)[i]^(*mix1)[i])+1;
  65.                /* Assume overflow ignored so 255+1==0 */
  66.          }
  67.       /* Shift rows */
  68.       for (j=0;j<high;j++) {
  69.          oldline = page2[j];
  70.          shift = (j%(wide-1))+1;
  71.          for (i=0;i<wide;i++) page1[i][j] = (*oldline)[(i+shift)%wide];
  72.          }
  73.       /* Eliminate any pattern (after first iteration only) */
  74.       if (k==0) unpat(page1,wide,high);
  75.       }
  76.    }
  77.  
  78. #else
  79. unshuffle(page1,code,wide,high)
  80.    line page1[LIMIT];  /* [width,height] */
  81.    line code;
  82.    int wide,high;
  83.    {
  84.    int i,j,k,key,shift;
  85.    line *mix1,*mix2;
  86.    line *newline,page2[LIMIT];  /* [height,width] */
  87.    for (k=0;k<SECURE;k++) {
  88. #if DEBUG
  89.       show(page1,wide,high);
  90. #endif
  91.       /* Eliminate any pattern (before last iteration only) */
  92.       if (k==SECURE-1) unpat(page1,wide,high);
  93.       /* Shift rows back */
  94.       for (j=0;j<high;j++) {
  95.          newline = page2[j];
  96.          shift = wide-(j%(wide-1))-1;
  97.          for (i=0;i<wide;i++) (*newline)[i] = page1[(i+shift)%wide][j];
  98.          }
  99.       /* Reverse mixup */
  100.       for (j=1;j<high;j+=2) {
  101.          mix1 = page2[j-1];
  102.          mix2 = page2[j];
  103.          for (i=0;i<wide;i++) (*mix2)[i] = ((*mix2)[i]-1)^(*mix1)[i];
  104.                 /*  Assume underflow is ignored so 0-1==255 */
  105.          }
  106.       /* Shift columns back */
  107.       for (i=0;i<wide;i++) {
  108.          newline = page1[i];
  109.          key = (int) code[i];
  110.          for (j=0;j<high;j++) (*newline)[(j+key)%high] = page2[j][i];
  111.          }
  112.       }
  113.    }
  114. #endif
  115.  
  116. show(page,wide,high)
  117.    line page[LIMIT];
  118.    int wide,high;
  119.    {
  120.    int i,j;
  121.    puts("\n");
  122.    for (j=0;j<high;j++) {
  123.       putc('\n',stdout);
  124.       for (i=0;i<wide;i++) {
  125.          if (page[i][j]<30) putc('*',stdout);
  126.          else putc(page[i][j],stdout);
  127.          }
  128.       }
  129.    }
  130.  
  131. main (argc,argv)
  132.    int argc;
  133.    char *argv[];
  134. {
  135.    FILE *infile,*outfile;
  136.    int wide,high,i,j,k;    /* Block width and height, loop counters */
  137.    int blkn = 1;           /* Block counter */
  138.    int clen;        /* Password code length */
  139.    long chksum;     /* Password checksum */
  140.    int ch = 0;
  141.    int invers;             /* Version of input file for decrypt */
  142.    int vers = 3;           /* Version of this program */
  143.    line page[LIMIT],code;
  144. #if ENCRYPT
  145.    int chrcnt;       /* Character counter */
  146.    long fsize;       /* Input file size */
  147.    int blocksize,nblocks;
  148.    struct time t;  /* For system time */
  149.    struct stat st; /* For input file stats */
  150.    /* Randomise the rand() function */
  151.    gettime(&t);
  152.    srand(t.ti_min*400+t.ti_sec*100+t.ti_hund); /* random seed <30000 */
  153.    /* Check the input arguments */
  154.    if (argc!=3) {puts("\nUsage is: tangle src dst\n"); exit(1);}
  155. #else
  156.    int blkcnt;
  157.    /* Check the input arguments */
  158.    if (argc!=3) {puts("\nUsage is: untangle src dst\n"); exit(1);}
  159. #endif
  160.    if ((infile = fopen(argv[1],"rb")) == NULL) {
  161.       printf("\n%s",argv[1]); perror(" "); exit(1);}
  162.    if ((outfile = fopen(argv[2],"wb")) == NULL) {
  163.       printf("\n%s",argv[2]); perror(" "); exit(1);}
  164. #if ENCRYPT
  165.    /* Get input file size */
  166.    if (stat(argv[1],&st)!=0) {perror(" "); exit(1);}
  167.    fsize = st.st_size;
  168.    printf("The input file size is %ld\n",fsize);
  169.    /* Choose block size accordingly */
  170.    if (fsize<(LIMIT*LIMIT)) blocksize = (int) fsize;
  171.    else {
  172.       nblocks = (int) (fsize/(LIMIT*LIMIT)+1);
  173.       blocksize = (int) (fsize/nblocks+1);
  174.       }
  175.    if (fsize<MINB) blocksize = MINB;    /* Minimum block size enforced */
  176.    wide = 0; while (wide*wide<blocksize) wide++;  /* Approx square root */
  177.    wide = wide+10; if (wide>LIMIT) wide = LIMIT;
  178.    high = blocksize/wide+1; if (high>LIMIT) high = LIMIT;
  179.    while (1) {
  180.       blocksize = wide*high;
  181.       if (fsize<(long) blocksize) break;
  182.       else {
  183.          /* Multiple blocks, check for last block too small */
  184.          if (((fsize-1)%blocksize)>(blocksize*3/4)) break;
  185.          /* (fsize-1) is used above so perfect fit is accepted! */
  186.          high--; wide--; /* Try a smaller block */
  187.          }
  188.       if (wide<50) break;
  189.       }
  190.    printf("The width and height are (%d,%d)\n",wide,high);
  191.    printf("The last block is %ld bytes\n",((fsize-1)%blocksize)+1);
  192.    fprintf(outfile,"%d,%d,%d,",vers,wide,high);
  193. #else
  194.    fscanf(infile,"%d,%d,%d,",&invers,&wide,&high);
  195.    if (invers!=vers) {
  196.       printf("This is version %d of the encryption program.\n",vers);
  197.       printf("The input file is for program version %d or invalid.\n",invers);
  198.       exit(1);
  199.       }
  200. #endif
  201.    /* Get password */
  202.    while(1) {
  203.       puts("\nPlease enter your password");
  204.       fgets(code,LIMIT,stdin);
  205.       clen = strlen(code);
  206.       if (clen>9) break;
  207.       puts("Insecure password, try a longer one.");
  208.       puts("For security do not use a name or word in any dictionary.");
  209.       puts("For example use something like \"Dazed and Konfuzed\"");
  210.       }
  211.    for (i=0;i<25;i++) puts(" ");   /* Clear the screen */
  212.    if (clen>wide) puts("Warning: tail of password ignored");
  213.    /* Extend password to possible limit, not null terminated */
  214.    for (i=clen;i<LIMIT;i++) code[i] = code[i%clen] ^ '\152';
  215.    /* Generate a checksum for the characters */
  216.    for (chksum=0,i=0;i<clen;i++) chksum += (int) code[i]*i;
  217.    printf("The password checksum is %ld.  Please wait ...\n",chksum % 1000);
  218.    do { /* tangle or untangle a block */
  219. #if ENCRYPT
  220.       chrcnt = 0;
  221. #else
  222.       if (fscanf(infile,"%d,",&blkcnt)==EOF) goto NOBLOCK;
  223. #endif
  224.       for (j=0;j<high;j++) {
  225.          for (i=0;i<wide;i++) {
  226.             if ((ch = getc(infile)) != EOF) {
  227.                page[i][j] = ch;
  228. #if ENCRYPT
  229.                chrcnt++;}
  230.             else if (i==0 && j==0) goto NOBLOCK; /* EOF at start of block! */
  231.             /* Pad the last block with existing junk */
  232.             else page[i][j] = page[rand()%wide][rand()%high];
  233. #else
  234.                ;}
  235.             else {puts("Error: unexpected end of file"); goto NOBLOCK;}
  236. #endif
  237.             }
  238.          }
  239. #if ENCRYPT
  240.       fprintf(outfile,"%d,",chrcnt);
  241.       shuffle(page,code,wide,high);
  242.       for (j=0;j<high;j++) for (i=0;i<wide;i++) putc(page[i][j],outfile);
  243. #else
  244.       unshuffle(page,code,wide,high);
  245.       for (j=0;j<high;j++) for (i=0;i<wide;i++)
  246.          if ((j*wide+i)<blkcnt) putc(page[i][j],outfile);
  247. #endif
  248.       printf("Finished block number %d\n",blkn++);
  249.       }
  250.    while (ch != EOF);
  251. NOBLOCK:                  /* Jump here to avoid writing an empty block */
  252.    for (i=0;i<LIMIT;i++) code[i] = ' ';   /* Rubout the password before exit */
  253.    fclose(infile);
  254.    fclose(outfile);
  255. }
  256. ------------------------------<author.txt>-------------------
  257. Alan Finlay
  258. Computer Science Dept.
  259. Monash University
  260. CLAYTON VIC 3168
  261. Australia
  262.  
  263. -------------------------
  264. email: alanf@bruce.oz.au
  265. N.B. I wrote this program on my own machine in my own time, hence it does
  266. not belong to Monash University.
  267. --------------------------------<algthm.txt>-----------------
  268. For each block, let us call it page[x,y] where 0<=x<wide and 0<=y<high:
  269. (it is understood that each line is for all x<wide and for all y<high)
  270. -----------------------------------------------------------------------
  271.    1) Do one shuffle:
  272.          page[x,y] := page[x,(y+key[x]) mod high]
  273.          if y is odd then page[x,y] := (page[x,y] XOR page[x,y-1])+1 mod 256
  274.          page[x,y] := page[(x+(y mod (wide-1))+1) mod wide,y]
  275.  
  276.    2) Perform a simple substitution:
  277.          page[x,y] := page[x,y] XOR ((x*high+y)*7 mod 256)
  278.  
  279.    3) Do 9 shuffles:
  280.          page[x,y] := page[x,(y+key[x]) mod high]
  281.          if y is odd then page[x,y] := (page[x,y] XOR page[x,y-1])+1 mod 256
  282.          page[x,y] := page[(x+(y mod (wide-1))+1) mod wide,y]
  283.  
  284. Each step in the process is easily reversible.
  285. -------------------------------------------------------------------------
  286.  
  287. The encrypted file format is:
  288.         1) Three decimal integers: program version number (= 3), wide, high.
  289.            Each as chars terminated by a comma (i.e. C format "%d,%d,%d,").
  290.         2) for each block:
  291.               The real number of characters in the block as a comma
  292.               terminated decimal integer (i.e. C format "%d,").
  293.               The block of bytes:
  294.                  for (j:=0..high-1), for (i:=0..wide-1) page[i,j]
  295.  
  296. -------------------------------------------------------------------------
  297. ---------------- end of Tangle 3.2 source distribution ------------------
  298.  
  299.  
  300.