home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / alde_c / misc / util / cipher2 / desmod.cv2 < prev    next >
Encoding:
Text File  |  1985-03-04  |  11.0 KB  |  321 lines

  1. /***************************** desmods *************************
  2.  * DESMODS: encrypt/decrypt bytes using the NBS DES algorithm.
  3.  * Programmed by R.W.Outerbridge; uses Jim Gillogly's DES.
  4.  *
  5.  * Usage: des (+|-)([ecb]|<cbc|cks>) key1 <ivec>
  6.  *              EN/DE   MODES           KEYS
  7.  *
  8.  *      + :     ENcrypt (default if MODE specified)
  9.  *      - :     DEcrypt (presumes encrypted input)
  10.  *
  11.  *      Modes of Operation (choose ONE):
  12.  *
  13.  *      ecb : (default) Electronic Code Book.  Only uses one key.
  14.  *              If simply "+" or "-" is specified, ecb is used.
  15.  *      cbc : Cipher Block Chaining.  Uses two keys.
  16.  *      cks : ChecKSum.  Generates a 64-bit checksum using two keys.
  17.  *
  18.  *      Both keys may be as long as you wish.  The practical limit
  19.  *      on keylength is the size of your system's argument buffer.
  20.  *      WARNING: on some machines all arguments become CAPITALS.
  21.  *      WARNING: non-ascii machines MAY get different results.
  22.  *
  23.  *      Any character may be used in keys - depending on the O/S -
  24.  *      except ASCII NULL (0x00).  The one letter key '#', when used 
  25.  *      for "key1", will cause desmods to use a preset default key
  26.  *      (for verification and testing).  Failing to specify "ivec", if
  27.  *      required, will result in "key1" being used for both keys.  It
  28.  *      is an error to omit "key1".  There is no provision for giving
  29.  *      arbitrary, absolute, bit-valued keys.
  30.  *
  31.  *      As painful as they are to use, long keys are MUCH safer;
  32.  *      think up nonsense phrases you can safely remember.
  33.  *
  34.  * 8501.29 : Default key ['#'] not erased from command line.  rwo
  35.  */
  36.  
  37. #include <stdio.h>
  38. #define toascii(a)      ((a)&0177)
  39. #define EN      0
  40. #define DE      1
  41. #define CKS     2
  42. #define MODS    6       /* three modes times two cases  */
  43. typedef char    BYTE;   /* BYTE = (vax) ? int : char    */
  44.         
  45. /* cryptographic declarations   */
  46. void copy8(), xor8(), getkey();
  47. BYTE Block[8], Link[8], Temp[8], IV[8];
  48. BYTE DFLTKY[8] = { 1,35,69,103,137,171,205,239 };
  49.         /* DO NOT ALTER! => 0x0123456789abcdef <=       */
  50.  
  51. extern void desinit(), kinit(), des();
  52.  
  53. /* I/O declarations     */
  54. void ruderr(), put8(), vraiput(), initio();
  55. int IOedf, End, Once;
  56. BYTE Last[8];
  57.  
  58. int Ecb(), Cbc(), Cks();
  59. struct modes {
  60.         char *name;
  61.         int (*func)();
  62.         };
  63. struct modes ModsOp[MODS] = {   /* Must be CAPs for CP/M        */
  64.         { "ecb", Ecb },
  65.         { "ECB", Ecb },
  66.         { "cbc", Cbc },
  67.         { "CBC", Cbc },
  68.         { "cks", Cks },
  69.         { "CKS", Cks }  };
  70.  
  71. main(argc, argv)
  72. int argc;
  73. char **argv;
  74.         {
  75.         int (*xeqtr)();
  76.         int step, ende, edio, ok, i;
  77.         BYTE kv[8];
  78.  
  79.         argv++; argc--;
  80.         if(argc > 3 || argc < 2) ruderr();
  81.         else desinit();
  82.  
  83.         for(step=0; argc > 0; step++) {
  84.                 switch(step) {
  85.                 case 0:         /* set en/de and/or default mode        */
  86.                         if(*argv[0] == '+' || *argv[0] == '-') {
  87.                                 ende = (*argv[0] == '+') ? EN : DE;
  88.                                 *argv[0]++ = NULL;
  89.                                 if(*argv[0] == NULL) {
  90.                                         xeqtr = Ecb;    /* default mode */
  91.                                         edio = ende;
  92.                                         argv++; argc--;
  93.                                         break;
  94.                                         }
  95.                                 }
  96.                         else ende = EN;
  97.  
  98.                         for(i=ok=0; i < MODS && !ok; i++) {
  99.                                 if(strcmp(argv[0], ModsOp[i].name) == 0) {
  100.                                         xeqtr = ModsOp[i].func;
  101.                                         ok = 1;
  102.                                         }
  103.                                 }
  104.                         if(!ok) {
  105.                                 fprintf(stderr,
  106.                                         "Des: unknown mode >%s<.\n", argv[0]);
  107.                                 ruderr();
  108.                                 }
  109.                         while(*argv[0]) *argv[0]++ = NULL;
  110.                         argv++; argc--;
  111.  
  112.                         /* set appropriate IO modes     */
  113.                         if(xeqtr == Cks) edio = CKS;
  114.                         else edio = ende;
  115.  
  116.                 /* falling through....  */
  117.                 case 1: /* get the key and IV, if needed and present    */
  118.                         if(strcmp(argv[0], "#") == 0) {
  119.                                 copy8(DFLTKY, kv);
  120.                                 *argv[0] = NULL;
  121.                                 }
  122.                         else getkey(argv[0], kv);
  123.                         argv++; argc--;
  124.                         
  125.                         /* if nothing left, but an IV needed, use the key */
  126.                         if(argc == 0) {
  127.                                 if(xeqtr != Ecb) copy8(kv, IV);
  128.                                 break;
  129.                                 }
  130.                         else if(xeqtr == Ecb) {
  131.                                 fprintf(stderr, "Des: ivec ignored.\n");
  132.                                 while(*argv[0]) *argv[0]++ = NULL;
  133.                                 argv++; argc--;
  134.                                 break;
  135.                                 }
  136.  
  137.                         else getkey(argv[0], IV);
  138.                         argv++; argc--;
  139.                         break;
  140.  
  141.                 default:
  142.                         fprintf(stderr, "Des: Programming error!\n");
  143.                         exit(1);
  144.                         break;
  145.                         }       /* switch       */
  146.                 }       /* argument parsing     */
  147.  
  148.         kinit(kv, ende);
  149.         initio(edio);
  150.         (*xeqtr)(ende); /* ta-da!       Take it away xeqtr!  */
  151.         exit(0);
  152.         }       /* end of main  */
  153.  
  154. void ruderr() {
  155.         fprintf(stderr, "Usage: des (+|-)([ecb]|<cbc|cks>) key1 <ivec>\n");
  156.         exit(1);
  157.         }
  158.  
  159. Cbc(e_d)        /* Cipher Block Chaining                */
  160. int e_d;        /* Ciphertext errors are self-healing.  */
  161.         {
  162.         copy8(IV, Link);
  163.         while(get8(Block) != EOF) {
  164.                 if(e_d == DE) {
  165.                         des(Block, Temp);
  166.                         xor8(Temp, Link);
  167.                         copy8(Block, Link);
  168.                         put8(Temp);
  169.                         }
  170.                 else {
  171.                         xor8(Block, Link);
  172.                         des(Block, Link);
  173.                         put8(Link);
  174.                         }
  175.                 }
  176.         return;
  177.         }
  178.  
  179. Cks(dummy)      /* CBC authentication checksum generator        */
  180. int dummy;      /* The banks use this for verifications.        */
  181.         {
  182.         int i, j, k;
  183.         long count = 0L;
  184.         copy8(IV, Link);
  185.         while(get8(Block) != EOF) {
  186.                 xor8(Block, Link);
  187.                 des(Block, Link);
  188.                 count++;
  189.                 }
  190.         fprintf(stdout, ": %0ld bytes\t: ", count<<3);
  191.         for(i=j=0; i < 2; i++) {
  192.                 for(k=0; k < 4; k++, j++)
  193.                         fprintf(stdout, "%02x", Link[j]&0377);
  194.                 putc(' ', stdout);
  195.                 }
  196.         fprintf(stdout, ":\n");
  197.         return;
  198.         }
  199.  
  200. Ecb(dummy)      /* Electronic Code Book : simple substitution   */
  201. int dummy;      /* Yawn.        For static data and random access.      */
  202.         {
  203.         while(get8(Block) != EOF) {
  204.                 des(Block, Block);
  205.                 put8(Block);
  206.                 }
  207.         return;
  208.         }
  209.  
  210. void copy8(from, to)
  211. register BYTE *from, *to;
  212.         {
  213.         register BYTE *ep;
  214.         ep = &to[8];
  215.         while(to < ep) *to++ = *from++;
  216.         return;
  217.         }
  218.  
  219. void xor8(to, with)
  220. register BYTE *to, *with;
  221.         {
  222.         register BYTE *ep;
  223.         ep = &to[8];
  224.         while(to < ep) *to++ ^= *with++;
  225.         return;
  226.         }
  227.  
  228. void put8(block)
  229. register BYTE *block;
  230.         {
  231.         if(IOedf == DE) copy8(block, Last);
  232.         else vraiput(block, &block[8]);
  233.         return;
  234.         }
  235.  
  236. get8(input)     /* KLUDGE: incomplete blocks handled sleazily   */
  237. register BYTE *input;
  238.         {
  239.         register int i, j;
  240.         if(End == 1) return(EOF);       /* no more input        */
  241.  
  242.         for(i=0; i < 8 && ((j = getc(stdin)) != EOF); i++) *input++ = j;
  243.  
  244.         if(IOedf == DE) {       /* DECRYPTION   */
  245.                 /* complete block?      pending output? */
  246.                 if(i == 8 && (Once > 0)) vraiput(Last, &Last[8]);
  247.                 else if(j == EOF) {
  248.                         End = 1;
  249.                         if(Once > 0) {
  250.                                 /* incomplete block means no nulls      */
  251.                                 if(i != 0) i = 0;
  252.                                 else {  
  253.                                         i = Last[7]&0377;
  254.                                         if(i > 8) i = 0;        /* huh? */
  255.                                         }
  256.                                 vraiput(Last, &Last[8-i]);
  257.                                 }
  258.                         return(EOF);
  259.                         }
  260.                 }
  261.         else if(j == EOF) {     /* ENCRYPTION   */
  262.                 End = 1;
  263.                 if(i == 0 && (IOedf == EN || (Once > 0))) {
  264.                         /* if no padding to do, print a kludge  */
  265.                         if(IOedf == EN && (Once > 0)) putc('0', stdout);
  266.                         return(EOF);
  267.                         }
  268.                 for(j=i; j < 7; j++) *input++ = NULL;
  269.                 *input = 8-i;
  270.                 }
  271.         Once = 1;
  272.         return(0);
  273.         }
  274.  
  275. void vraiput(cp, ep)
  276. register BYTE *cp, *ep;
  277.         {
  278.         while(cp < ep) putc((char)*cp++, stdout);
  279.         return;
  280.         }
  281.  
  282. void initio(edf)        /* use this as a hook on systems without UNIX   */
  283. int edf;
  284.         {
  285.         IOedf = edf;
  286.         End = Once = 0;
  287.         return;
  288.         }
  289.  
  290. void getkey(aptr, kptr)
  291. register char *aptr;
  292. register BYTE *kptr;
  293.         {
  294.         register BYTE *store;
  295.         register int i, first;
  296.         BYTE hold[8];
  297.         store = kptr;
  298.         first = 1;
  299.         kinit(DFLTKY, EN);
  300.         copy8(DFLTKY, hold);
  301.         while(*aptr || first) {
  302.                 kptr = store;
  303.                 for(i=0; i<8 && (*aptr != NULL); i++) {
  304.                         *kptr++ = toascii(*aptr);
  305.                         *aptr++ = NULL;
  306.                         }
  307.                 while(i++ < 8) *kptr++ = NULL;
  308.                 xor8(store, hold);
  309.                 des(store, hold);
  310.                 first = 0;
  311.                 }
  312.         copy8(hold, store); 
  313.         return;
  314.         }
  315.  
  316. /* des cks # < /dev/null 
  317.  *      : 8 bytes       : c9574425 6a5ed31d :
  318.  *      : (-DKSX64)     : acdcebea eb77deaa :
  319.  *                      (rwo/8502.16.18:30/V1.2)                */
  320. /************************* desmods ******************************/
  321.