home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 509.lha / DES / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  4.7 KB  |  248 lines

  1. /* Encrypt/decrypt command compatible with Sun's "des" command */
  2. #include <stdio.h>
  3.  
  4. char iv[8];    /* Initial vector for CBC mode */
  5. int block;
  6.  
  7. main(argc,argv)
  8. int argc;
  9.  
  10. char *argv[];
  11.  
  12. {
  13.     int c,cnt,encrypt,decrypt,hexflag,help,outfile, infile;
  14.     register int i;
  15.     char key[8],tkey1[20],tkey2[20],*akey,*getpass(), *inname, *outname;
  16.     extern char *optarg;
  17.     FILE    *instreme = stdin;        
  18.     FILE    *outstreme = stdout;    
  19.     FILE     *fp, *fp2, *fopen();
  20.  
  21.     hexflag = infile = help = outfile = block = encrypt = decrypt = 0;
  22.     akey = NULL;
  23.     while((c = getopt(argc,argv,"hedk:bi:o:?")) != EOF){
  24.         switch(c){
  25.         case 'h':
  26.             hexflag++;
  27.             break;
  28.         case 'e':
  29.             encrypt++;
  30.             break;
  31.         case 'd':
  32.             decrypt++;
  33.             break;
  34.         case 'k':
  35.             akey = optarg;
  36.             break;
  37.         case 'b':
  38.             block++;
  39.             break;
  40.         case 'i':
  41.             infile++;
  42.             inname = optarg;
  43.             break;
  44.         case 'o':
  45.             outfile++;
  46.             outname = optarg;
  47.             break;
  48.         case '?':
  49.             help++;
  50.             break;
  51.         }
  52.     }
  53.     if((encrypt == 0 && decrypt == 0) || (akey == NULL)||(help)){
  54.         fprintf(stderr,"Usage: des -e|-d [-b] [-h] -k key [-i infile] [-o outfile] [-?]\n");
  55.         if(help){
  56.             printf("\nArgs:\n-e To encrypt\t-d To decrypt\n");
  57.             printf("-b Electronic Code Book -- uses 8 byte chunks to encrypt\n");
  58.             printf("\tSlight weaker than default CBC but useful for data with errors.\n");
  59.             printf("\n-h Hex input\t-k 8 byte key\n");
  60.             printf("-i Inputfile\t-o Outputfile\n");
  61.             printf("\t optional -- stdin and/or stdout fine.\n");
  62.             printf("-? This help message\n\n");
  63.         }
  64.         exit(2);
  65.     }
  66.     
  67.     if(hexflag){
  68.         for(i=0;i<16;i++){
  69.             if(htoa(akey[i]) == -1){
  70.                 fprintf(stderr,"Non-hex character in key\n");
  71.                 exit(1);
  72.             }
  73.         }
  74.         gethex(key,akey,8);
  75.     } else {
  76.         strncpy(key,akey,8);
  77.         /* Set up key, determine parity bit */
  78.         for(cnt = 0; cnt < 8; cnt++){
  79.             c = 0;
  80.             for(i=0;i<7;i++)
  81.                 if(key[cnt] & (1 << i))
  82.                     c++;
  83.             if((c & 1) == 0)
  84.                 key[cnt] |= 0x80;
  85.             else
  86.                 key[cnt] &= ~0x80;
  87.         }
  88.     }
  89.     /*tacked on file junk*/
  90.     if(infile){
  91.         if((fp=fopen(inname, "r")) != NULL)
  92.             instreme = fp;
  93.         
  94.         else {
  95.             fprintf(stderr,"Input file not opened.\n");
  96.             exit(1);
  97.         }
  98.     }
  99.     if(outfile) {
  100.         if((fp2=fopen(outname,"w")) !=NULL)
  101.             outstreme = fp2;
  102.         else {
  103.             fprintf(stderr,"Output file not opened.\n");
  104.             exit(1);
  105.         }
  106.     }
  107.     /* Blot out original key */
  108.     i = strlen(akey);
  109.     i = (i < 8) ? i : 8;
  110.     memset(akey,0,i);
  111.     
  112.     desinit(0);
  113.     setkey(key);
  114.  
  115.     /* Initialize IV to all zeros */
  116.     memset(iv,0,8);
  117.  
  118.     if(encrypt){
  119.         doencrypt(instreme,outstreme);
  120.     }
  121.     else {
  122.         dodecrypt(instreme,outstreme);
  123.     }
  124.     if(infile)
  125.         fclose(fp);
  126.     if(outfile)
  127.         fclose(fp2);
  128. }
  129. /* Encrypt standard input to standard output */
  130. doencrypt(instreme,outstreme)
  131. FILE *instreme, *outstreme;
  132.  
  133. {
  134.     char work[8],*cp,*cp1;
  135.     int cnt,i;
  136.  
  137.     for(;;){
  138.         if((cnt = fread(work,1,8,instreme)) != 8){
  139.             /* Put residual byte count in the last block.
  140.              * Note that garbage is left in the other bytes,
  141.              * if any; this is a feature, not a bug, since it'll
  142.              * be stripped out at decrypt time.
  143.              */
  144.             work[7] = cnt;
  145.         }
  146.         if(!block){
  147.             /* CBC mode; chain in last cipher word */
  148.             cp = work;
  149.             cp1 = iv;
  150.             for(i=8; i!=0; i--)
  151.                 *cp++ ^= *cp1++;
  152.         }
  153.         endes(work);    /* Encrypt block */
  154.         if(!block){    /* Save outgoing ciphertext for chain */
  155.             memcpy(iv,work,8);
  156.         }
  157.         fwrite(work,1,8,outstreme);
  158.         if(cnt != 8)
  159.             break;
  160.     }
  161. }
  162. dodecrypt(instreme,outstreme)
  163. FILE *instreme, *outstreme;
  164.  
  165. {
  166.     char work[8],nwork[8],ivtmp[8],*cp,*cp1;
  167.     int cnt,i;
  168.  
  169.  
  170.     cnt = fread(work,1,8,instreme);    /* Prime the pump */
  171.     for(;;){
  172.         if(!block){    /* Save incoming ciphertext for chain */
  173.             memcpy(ivtmp,work,8);
  174.         }
  175.         dedes(work);
  176.         if(!block){    /* Unchain block, save ciphertext for next */
  177.             cp = work;
  178.             cp1 = iv;
  179.             for(i=8; i!=0; i--){
  180.                 *cp++ ^= *cp1++;
  181.             }
  182.             memcpy(iv,ivtmp,8);
  183.         }
  184.         /* Save buffer pending next read */
  185.         memcpy(nwork,work,8);
  186.         /* Try to read next block */
  187.         cnt = fread(work,1,8,instreme);
  188.         if(cnt != 8){    /* Can "only" be 0 if not 8 */
  189.             /* Prev block was last one, write appropriate number
  190.              * of bytes
  191.              */
  192.             cnt = nwork[7];
  193.             if(cnt < 0 || cnt > 7){
  194.                 fprintf(stderr,"Corrupted file or wrong key\n");
  195.             } else if(cnt != 0)
  196.                 fwrite(nwork,1,cnt,outstreme);
  197.             exit(0);
  198.         } else {
  199.             /* Now okay to write previous buffer */
  200.             fwrite(nwork,1,8,outstreme);
  201.         }
  202.  
  203.     }
  204. }
  205. /* Convert hex/ascii nybble to binary */
  206. int
  207. htoa(c)
  208. char c;
  209. {
  210.     if(c >= '0' && c <= '9')
  211.         return c - '0';
  212.     if(c >= 'a' && c <= 'f')
  213.         return 10 + c - 'a';
  214.     if(c >= 'A' && c <= 'F')
  215.         return 10 + c - 'A';
  216.     return -1;
  217. }
  218. /* Convert bytes from hex/ascii to binary */
  219. gethex(result,cp,cnt)
  220. register char *result;
  221. register char *cp;
  222. register int cnt;
  223. {
  224.     while(cnt-- != 0){
  225.         *result = htoa(*cp++) << 4;
  226.         *result++ |= htoa(*cp++);
  227.     }
  228. }
  229. #ifdef    DEBUG
  230. put8(cp)
  231. register char *cp;
  232. {
  233.     int i;
  234.  
  235.     for(i=0;i<8;i++){
  236.         fprintf(stderr,"%02x ",*cp++ & 0xff);
  237.     }
  238. }
  239. #endif
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.