home *** CD-ROM | disk | FTP | other *** search
/ Boldly Go Collection / version40.iso / TS / 17A / DES_1991.ZIP / MAIN.C < prev    next >
C/C++ Source or Header  |  1991-06-21  |  4KB  |  204 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. char ks[16][8];
  7.  
  8. main(argc,argv)
  9. int argc;
  10. char *argv[];
  11. {
  12.     int c,cnt,encrypt,decrypt,hexflag;
  13.     register int i;
  14.     char key[8],tkey1[20],tkey2[20],*akey,*getpass();
  15.     extern char *optarg;
  16.  
  17.     hexflag = block = encrypt = decrypt = 0;
  18.     akey = NULL;
  19.     while((c = getopt(argc,argv,"hedk:b")) != EOF){
  20.         switch(c){
  21.         case 'h':
  22.             hexflag++;
  23.             break;
  24.         case 'e':
  25.             encrypt++;
  26.             break;
  27.         case 'd':
  28.             decrypt++;
  29.             break;
  30.         case 'k':
  31.             akey = optarg;
  32.             break;
  33.         case 'b':
  34.             block++;
  35.             break;
  36.         }
  37.     }
  38.     if(encrypt == 0 && decrypt == 0){
  39.         fprintf(stderr,"Usage: des -e|-d [-h] [-k key]\n");
  40.         exit(2);
  41.     }
  42.     if(akey == NULL){
  43.         /* No key on command line, prompt for it */
  44.         memset(tkey1,0,sizeof(tkey1));
  45.         memset(tkey2,0,sizeof(tkey2));
  46.         for(;;){
  47.             akey = getpass("Enter key: ");
  48.             strncpy(tkey1,akey,sizeof(tkey1));
  49.             akey = getpass("Enter key again: ");
  50.             strncpy(tkey2,akey,sizeof(tkey2));
  51.             if(strncmp(tkey1,tkey2,sizeof(tkey1)) != 0){
  52.                 fprintf(stderr,"Key mistyped, try again\n");
  53.             } else
  54.                 break;
  55.         }
  56.         akey = tkey1;
  57.     }
  58.     if(hexflag){
  59.         for(i=0;i<16;i++){
  60.             if(htoa(akey[i]) == -1){
  61.                 fprintf(stderr,"Non-hex character in key\n");
  62.                 exit(1);
  63.             }
  64.         }
  65.         gethex(key,akey,8);
  66.     } else {
  67.         strncpy(key,akey,8);
  68.         /* Set up key, determine parity bit */
  69.         for(cnt = 0; cnt < 8; cnt++){
  70.             c = 0;
  71.             for(i=0;i<7;i++)
  72.                 if(key[cnt] & (1 << i))
  73.                     c++;
  74.             if((c & 1) == 0)
  75.                 key[cnt] |= 0x80;
  76.             else
  77.                 key[cnt] &= ~0x80;
  78.         }
  79.     }
  80.     /* Blot out original key */
  81.     i = strlen(akey);
  82.     i = (i < 8) ? i : 8;
  83.     memset(akey,0,i);
  84.  
  85.     desinit(0);
  86.     setkey(ks,key);
  87.  
  88.     /* Initialize IV to all zeros */
  89.     memset(iv,0,8);
  90.  
  91.     if(encrypt){
  92.         doencrypt();
  93.     } else {
  94.         dodecrypt();
  95.     }
  96. }
  97. /* Encrypt standard input to standard output */
  98. doencrypt()
  99. {
  100.     char work[8],*cp,*cp1;
  101.     int cnt,i;
  102.  
  103.     for(;;){
  104.         if((cnt = fread(work,1,8,stdin)) != 8){
  105.             /* Put residual byte count in the last block.
  106.              * Note that garbage is left in the other bytes,
  107.              * if any; this is a feature, not a bug, since it'll
  108.              * be stripped out at decrypt time.
  109.              */
  110.             work[7] = cnt;
  111.         }
  112.         if(!block){
  113.             /* CBC mode; chain in last cipher word */
  114.             cp = work;
  115.             cp1 = iv;
  116.             for(i=8; i!=0; i--)
  117.                 *cp++ ^= *cp1++;
  118.         }
  119.         endes(ks,work);    /* Encrypt block */
  120.         if(!block){    /* Save outgoing ciphertext for chain */
  121.             memcpy(iv,work,8);
  122.         }
  123.         fwrite(work,1,8,stdout);
  124.         if(cnt != 8)
  125.             break;
  126.     }
  127. }
  128. dodecrypt()
  129. {
  130.     char work[8],nwork[8],ivtmp[8],*cp,*cp1;
  131.     int cnt,i;
  132.  
  133.  
  134.     cnt = fread(work,1,8,stdin);    /* Prime the pump */
  135.     for(;;){
  136.         if(!block){    /* Save incoming ciphertext for chain */
  137.             memcpy(ivtmp,work,8);
  138.         }
  139.         dedes(ks,work);
  140.         if(!block){    /* Unchain block, save ciphertext for next */
  141.             cp = work;
  142.             cp1 = iv;
  143.             for(i=8; i!=0; i--){
  144.                 *cp++ ^= *cp1++;
  145.             }
  146.             memcpy(iv,ivtmp,8);
  147.         }
  148.         /* Save buffer pending next read */
  149.         memcpy(nwork,work,8);
  150.         /* Try to read next block */
  151.         cnt = fread(work,1,8,stdin);
  152.         if(cnt != 8){    /* Can "only" be 0 if not 8 */
  153.             /* Prev block was last one, write appropriate number
  154.              * of bytes
  155.              */
  156.             cnt = nwork[7];
  157.             if(cnt < 0 || cnt > 7){
  158.                 fprintf(stderr,"Corrupted file or wrong key\n");
  159.             } else if(cnt != 0)
  160.                 fwrite(nwork,1,cnt,stdout);
  161.             exit(0);
  162.         } else {
  163.             /* Now okay to write previous buffer */
  164.             fwrite(nwork,1,8,stdout);
  165.         }
  166.  
  167.     }
  168. }
  169. /* Convert hex/ascii nybble to binary */
  170. int
  171. htoa(c)
  172. char c;
  173. {
  174.     if(c >= '0' && c <= '9')
  175.         return c - '0';
  176.     if(c >= 'a' && c <= 'f')
  177.         return 10 + c - 'a';
  178.     if(c >= 'A' && c <= 'F')
  179.         return 10 + c - 'A';
  180.     return -1;
  181. }
  182. /* Convert bytes from hex/ascii to binary */
  183. gethex(result,cp,cnt)
  184. register char *result;
  185. register char *cp;
  186. register int cnt;
  187. {
  188.     while(cnt-- != 0){
  189.         *result = htoa(*cp++) << 4;
  190.         *result++ |= htoa(*cp++);
  191.     }
  192. }
  193. #ifdef    DEBUG
  194. put8(cp)
  195. register char *cp;
  196. {
  197.     int i;
  198.  
  199.     for(i=0;i<8;i++){
  200.         fprintf(stderr,"%02x ",*cp++ & 0xff);
  201.     }
  202. }
  203. #endif
  204.