home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / sci / crypt / 6057 < prev    next >
Encoding:
Text File  |  1992-12-22  |  8.5 KB  |  331 lines

  1. Xref: sparky sci.crypt:6057 alt.sources:2853
  2. Path: sparky!uunet!news.gtech.com!noc.near.net!hri.com!spool.mu.edu!agate!dog.ee.lbl.gov!network.ucsd.edu!qualcom.qualcomm.com!cancun!rdippold
  3. From: rdippold@cancun.qualcomm.com (Ron Dippold)
  4. Newsgroups: sci.crypt,alt.sources
  5. Subject: WPUNCRYPT.C
  6. Message-ID: <rdippold.725047499@cancun>
  7. Date: 22 Dec 92 18:04:59 GMT
  8. Sender: news@qualcomm.com
  9. Organization: Qualcomm, Inc., San Diego, CA
  10. Lines: 318
  11. Nntp-Posting-Host: cancun.qualcomm.com
  12.  
  13. /*----------------------------------------------------------------------
  14. **  WPUNCRPY - Copyright (c) 1990, 91 Ron Dippold 10/11/91
  15. **  rdippold@qualcomm.com
  16. **
  17. **  Attempt to decrypt a Word Perfect file once you know the password.
  18. **  This is just so that Word Perfect isn't needed.
  19. **
  20. **  This source code is hereby released for public use.  All I ask is
  21. **  that if you make some cool new additions or enhancements that you
  22. **  mail me the update.  And if you use the program or source code,
  23. **  give me a little credit.
  24. **
  25. **  I'm not claiming this is the best code you've ever seen, it's just
  26. **  a fast hack, but it works.  I tried to be generic as possible so
  27. **  that it will compile on almost any platform.  It was written under
  28. **  Borland C.
  29. **----------------------------------------------------------------------*/
  30.  
  31. #include <stdio.h>
  32. #include <string.h>
  33.  
  34. FILE *fin, *fout;
  35. char *inname, *outname, *pass;
  36.  
  37. typedef unsigned char byte;
  38. typedef unsigned int  word;
  39.  
  40. word ver5 = 0;                                /* version 4 or 5 */
  41. word override = 0;            /* override checksum */
  42. word pause = 0;               /* pause on screen */
  43. word text = 0;                /* text mode */
  44. word soft = 0;                /* translate CR as a space in text mode */
  45.  
  46. long tstart;                                    /* start of text position */
  47. long pos;                     /* position in file */
  48. word lines, chars;            /* lines of text */
  49.  
  50. word plen;                    /* password length */
  51. word csum, csum1;             /* checksum */
  52.  
  53. word len;                     /* bytes to read */
  54. word idx;                     /* index into buffer */
  55.  
  56. byte buf[4096], c;
  57.  
  58. word pidx;                    /* index down password */
  59. byte xmask;                   /* XOR mask */
  60.  
  61. int i, j, k;
  62.  
  63. void docs() {
  64.     printf( " To uncrypt a Word Perfect 4.x or 5.x file, the syntax is:\n\n");
  65.     printf("    WPUNCRYP (-o) (-p) (-b) w|t \"password\" <input file> (<output file>) \n\n");
  66.     printf("  Use the 'w' command to decrypt <input file> into <output file>\n");
  67.     printf("    in Word Perfect format.  This option is meaningless if <output\n");
  68.     printf("    file> is not given.\n");
  69.     printf("  Use the 't' command to decrypt the text portion of <input file>.\n");
  70.     printf("    This will not remove any embedded formatting codes, you can do\n");
  71.     printf("    that yourself!\n");
  72.     printf(" If <output file> is not given, the decrypted text will be shown to\n");
  73.     printf("    the screen.\n");
  74.     printf(" The optional -o switch will force the decrpytion even if the checksum\n");
  75.     printf("    of the password doesn't match the checksum of the file.\n");
  76.     printf(" The optional -p switch will make the make WPUNCRYP attempt to pause\n");
  77.     printf("    after every screen of output to the screen.\n");
  78.   printf(" In text output mode, both hard and soft line breaks are output as a\n");
  79.   printf("    CR/LF.  The optional -b will translate the soft break as a space.\n");
  80.     exit(1);
  81. }
  82.  
  83. void main( int argc, char **argv )
  84. {
  85.     printf( "\nWPUNCRYP 1.0 - Copyright (c) 1990,91 Ron Dippold\n\n" );
  86.  
  87.     if( argc <4 || argc > 7 ) {
  88.         docs();
  89.     }
  90.  
  91.     i=1;
  92.   override = pause = text = soft = 0;
  93.  
  94.     while( i<argc && argv[i][0] == '-' ) {
  95.     switch( argv[i][1] ) {
  96.       case 'o':
  97.       case 'O':
  98.               override = 1;
  99.         break;
  100.       case 'p':
  101.       case 'P':
  102.                 pause = 1;
  103.         break;
  104.       case 'b':
  105.       case 'B':
  106.         soft = 1;
  107.         break;
  108.       default:
  109.                 docs();
  110.         }
  111.         i++;
  112.     }
  113.  
  114.     if( i>= argc-2 ) {
  115.         docs();
  116.     }
  117.  
  118.   if( argv[i][1]!='\0' ) docs();
  119.   if( argv[i][0]=='t' ) {
  120.     text = 1;
  121.   } else {
  122.         if( argv[i][0]=='w' ) {
  123.       text = 0;
  124.         } else {
  125.       docs();
  126.     }
  127.     }
  128.   i++;
  129.  
  130.     pass = argv[i++];
  131.   plen = strlen( pass );
  132.  
  133.   inname = argv[i++];
  134.  
  135.   if( i< argc ) {
  136.         outname = argv[i];
  137.         pause = 0;
  138.     } else {
  139.         outname = NULL;
  140.         text = 1;
  141.     }
  142.  
  143.     if( i > argc ) {
  144.         docs();
  145.     }
  146.  
  147.   if( !text ) {
  148.     soft = 0;
  149.   }
  150.  
  151.  
  152.     if( !( fin = fopen( inname, "rb" ))) {
  153.         printf( "  Could not open file %s\n", inname );
  154.         exit( 2 );
  155.     }
  156.  
  157.     fseek( fin, 0L, SEEK_SET );
  158.     if( fread( buf, 1, 4, fin ) != 4) {
  159.         fclose( fin );
  160.         printf( "  Couldn't read 4 bytes from file %s!\n", inname );
  161.         exit( 3 );
  162.     }
  163.  
  164.     if( buf[0]==0xff && buf[1]==0x57 && buf[2]==0x50 && buf[3]==0x43 ) {
  165.         printf( "  This is a Word Perfect 5.x file.\n");
  166.         ver5 = 1;
  167.     } else {
  168.         if( buf[0]==0xfe && buf[1]==0xff && buf[2]==0x61 && buf[3]==0x61 ) {
  169.             printf( " This is a Word Perfect 4.1 encrypted file.\n");
  170.         } else {
  171.             fclose( fin );
  172.             printf( "  The identification bytes in this file are not those of a\n" );
  173.             printf( "  Word Perfect 5.x or 4.x encrpyted file.\n" );
  174.             exit( 4 );
  175.         }
  176.     }
  177.  
  178.   if( ver5 ) {
  179.       if( fread( &buf[4], 1, 12, fin ) != 12 ) {
  180.           fclose( fin );
  181.             printf( "  Couldn't read the first 16 bytes of the file - garbaged!\n" );
  182.           exit( 5 );
  183.       }
  184.  
  185.         if( buf[12]==0 && buf[13]==0 ) {
  186.             printf( "  The file claims it is not encrypted.\n" );
  187.             fclose( fin ); exit( 6 );
  188.       }
  189.     }
  190.  
  191.   /* Now read the checksum */
  192.   if( ver5 ) {
  193.         csum1 = (buf[12]<<8) + buf[13];
  194.     } else {
  195.       if( fread( &buf, 1, 2, fin ) != 2) {
  196.       printf( "  Couldn't read checksum - short file!\n");
  197.             fclose( fin ); exit( 7 );
  198.     }
  199.         csum1 = (buf[4]<<8) + buf[5];
  200.   }
  201.  
  202.   csum = 0;
  203.   for( i=0; i<plen; i++ ) {
  204.     if( pass[i]>='a' && pass[i]<='z') {   /* convert to upper case */
  205.             pass[i] -= 'a'-'A';
  206.         }
  207.         csum = ( (csum >> 1) | ( csum << 15) ) ^ ( pass[i]<<8 );
  208.     }
  209.  
  210.     if( csum != csum1 ) {
  211.         if( override ) {
  212.             printf( "  Warning!  Password checksum does not match file checksum!\n");
  213.             printf( "  Any output is suspect.\n");
  214.         } else {
  215.             printf( "  The password checksum does not match the checksum in the file.\n");
  216.             printf( "  If you are convinced it is right, check the docs for the -o option.\n");
  217.             fclose( fin ); exit( 8 );
  218.         }
  219.     }
  220.  
  221.     /* get start of text */
  222.     if( ver5) {
  223.         tstart = *((long *) (&buf[4]));
  224.     pos = 16;
  225.     } else {
  226.         tstart = pos = 6;
  227.     }
  228.  
  229.     if( outname ) {
  230.         if( !( fout = fopen( outname, text ? "wt":"wb" ))) {
  231.             printf( "  Could not open file %s\n", outname );
  232.             exit( 2 );
  233.         }
  234.       fseek( fout, 0L, SEEK_SET );
  235.     } else {
  236.         fout = NULL;
  237.     }
  238.  
  239.     if( ver5 && fout && !text ) {
  240.         buf[12] = buf[13] = 0;        /* write out first part of WP5.1 file */
  241.         fwrite( &buf[0], 1, 16, fout );
  242.     }
  243.  
  244.     pidx = 0;                       /* start of password */
  245.     xmask = plen+1;                 /* start at password length+1 */
  246.  
  247.     if( ver5 ) {                    /* get rid of printer info, etc. */
  248.         while( pos<tstart ) {
  249.             if( tstart-pos > 4096 ) {
  250.                 len = 4096;
  251.             } else {
  252.                 len = tstart-pos;
  253.             }
  254.             if( fread( buf, 1, len, fin ) !=len ) {
  255.                 printf( "\n  Unexpected end of file for %s.\n", inname );
  256.                 fclose( fin ); fclose( fout ); exit( 20 );
  257.             }
  258.             for( idx=0; idx<len; idx++ ) {      /* now decrypt */
  259.                 buf[idx] ^= pass[pidx++] ^ xmask++;
  260.                 if( pidx == plen ) pidx = 0;
  261.             }
  262.             if( fout && !text ) {
  263.                 if( fwrite( buf, 1, len, fout ) !=len ) {
  264.                     printf( "\n  Couldn't write %d bytes to %s.\n", len, outname );
  265.                     fclose( fin ); fclose( fout ); exit( 20 );
  266.                 }
  267.             }
  268.             pos += len;
  269.         } /* while */
  270.     } /* ver5 */
  271.  
  272.     idx = len = 0;                  /* no data yet */
  273.     lines = chars = 0;              /* no lines shown */
  274.  
  275.     do {
  276.  
  277.         /* read from file as necessary */
  278.         if( idx>=len ) {
  279.             if( len>0 && fout ) {
  280.                 if( fwrite( buf, 1, len, fout ) !=len ) {
  281.                     printf( "\n  Couldn't write %d bytes to %s.\n", len, outname );
  282.                     fclose( fin ); fclose( fout ); exit( 20 );
  283.                 }
  284.             }
  285.             len = fread( buf, 1, 4096, fin );
  286.             pos += len;
  287.             if( len == 0 ) {
  288.                 break;                    /* all done with file */
  289.             }
  290.             idx = 0;
  291.         }
  292.  
  293.         c = buf[idx] ^= pass[pidx++] ^ xmask++;
  294.         if( pidx == plen ) pidx = 0;
  295.  
  296.         if( text ) {
  297.             if( c == 0xA9 ) buf[idx] = '-'; /* translate annoying dashes */
  298.             if( c == 0x0D ) {           /* handle soft break */
  299.                 if( soft ) {
  300.                     buf[idx] = ' ';
  301.                 } else {
  302.                     buf[idx] = '\n';
  303.                 }
  304.             }
  305.         }
  306.  
  307.  
  308.         if( !fout ) {
  309.             printf( "%c",c = buf[idx] );
  310.             if( c == '\n' || ++chars == 80) {
  311.                 lines++; chars=0;
  312.                 if( lines == 24 && pause) {
  313.                     getch();
  314.                     lines = 0;
  315.                 }
  316.             }
  317.         }
  318.  
  319.         idx++;
  320.  
  321.     } while( 1 );
  322.  
  323.     fclose( fin );
  324.     if( fout) fclose( fout );
  325. }
  326.  
  327.  
  328. -- 
  329. I'm not worried about the bullet with my name on it... just the
  330. thousands out there marked 'Occupant'
  331.