home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 144.lha / LCrypt.c < prev    next >
C/C++ Source or Header  |  1986-11-21  |  14KB  |  449 lines

  1. /**********************************************************************
  2.  *
  3.  *                        LCrypt.c 03/06/88
  4.  *
  5.  *       Original cipher code lifted, almost verbatim, from LUCIFER.C
  6.  *    by R.W. Outerbridge. I'm not sure that this code is copyrighted,
  7.  *    no mention of it's status was present in the orginal source file.
  8.  *
  9.  *       The original MS-DOS source was aquired from the Cryptography BBS,
  10.  *    (703) 237-4322 McLean VA.
  11.  *
  12.  *       Command line interface code by Jack Radigan. This code is
  13.  *    is free of any restrictions, You are free to include and/or
  14.  *    modifiy for your use in any program, commercial or otherwise.
  15.  *
  16.  *       A one line blurb of credit in your source would be nice though...
  17.  *
  18.  *       Compiled with Aztec C vers. 3.40a
  19.  *
  20.  ***********************************************************************/
  21.  
  22.  
  23. #include <stdio.h>
  24.  
  25. #define toascii(a)      ((a)&0177)
  26. #define EN 0
  27. #define DE 1
  28.  
  29. typedef char BYTE;
  30.  
  31. int IOedf, End, Once, crypt_flag;
  32.  
  33. char output[132], dir[35], temp[132], *rindex();
  34.         
  35. BYTE Block[16], Link[16], Temp[16], IV[16], Last[16];
  36.  
  37. BYTE DFLTKY[16] = { 1,35,69,103,137,171,205,239,254,220,186,152,118,84,50,16 };
  38.  
  39. FILE *fp_in, *fp_out;
  40.  
  41. main(argc, argv)
  42. int argc;
  43. char **argv;
  44. {
  45.    int c, i, j, k, count;
  46.    char *filename, *s, *fn[500];
  47.    char *scdir(), *malloc();
  48.    BYTE kv[16];
  49.  
  50.    printf("LCrypt 1.0 1988 by Jack Radigan\n");
  51.  
  52.    if(*argv[1] == '?')
  53.       help();
  54.       
  55.    if(argc < 3)
  56.       useage_error();
  57.  
  58.    crypt_flag = EN;
  59.    if(strlen(argv[1]) == 1) {      
  60.       if(*argv[1] != 'e' && *argv[1] != 'E' && *argv[1] != 'd' &&
  61.          *argv[1] != 'D')
  62.             useage_error();
  63.  
  64.       if(*argv[1] == 'd' || *argv[1] == 'D')
  65.          crypt_flag = DE;
  66.       argv++;
  67.       argc--;
  68.    }
  69.    if(*argv[1] == '-') {
  70.       strcpy(dir, argv[1] + 1);
  71.       if(dir[strlen(dir) - 1] != ':' && dir[strlen(dir) - 1] != '/') {
  72.          printf("Illegal directory specification!\n");
  73.          exit(0);
  74.       }
  75.       argv++;
  76.       argc--;
  77.    }
  78.    getkey(argv[1], kv);
  79.  
  80.    j = 0;
  81.    printf("Creating file list,");
  82.    fflush(stdout);
  83.    for(i = 2; i < argc; i++) {
  84.       strcpy(temp, argv[i]);
  85.       if(crypt_flag)
  86.          if(strcmp(temp + strlen(temp) - 3, ".lu"))
  87.             strcat(temp, ".lu");
  88.  
  89.       while((filename = scdir(temp)) && j < 500) {
  90.          fn[j] = malloc(strlen(filename) + 1);
  91.          strcpy(fn[j++], filename);
  92.       }
  93.    }
  94.    printf(" %d files found.\n", j);
  95.    for(i = 0; i < j; i++) {
  96.       strcpy(output, fn[i]);
  97.  
  98.       if((fp_in = fopen(output, "r")) == NULL) {
  99.          printf("Unable to open input file.\n");
  100.          continue;
  101.       }
  102.       if((fp_out = fopen("ram:LCrypt.tmp", "w")) == NULL) {
  103.          fclose(fp_in);
  104.          printf("Unable to open temporary file in ram:, exiting.\n");
  105.          exit(0);
  106.       }
  107.       printf("%s ", output);
  108.       fflush(stdout);
  109.       loadkey(kv, crypt_flag);
  110.       initio(crypt_flag);
  111.  
  112.       while(get16(Block) != EOF) {
  113.          lucifer(Block);
  114.          put16(Block);
  115.       }
  116.       fclose(fp_in);
  117.       fclose(fp_out);
  118.  
  119.       strcpy(temp, dir);
  120.       if(s = rindex(output, '/'))
  121.          s++;
  122.       else if(s = rindex(output, ':'))
  123.          s++;
  124.       else
  125.          s = output;
  126.       strcat(temp, s);
  127.       
  128.       if((fp_in = fopen("ram:LCrypt.tmp", "r")) == NULL)
  129.          continue;
  130.       if((fp_out = fopen(temp, "w")) == NULL) {
  131.          fclose(fp_in);
  132.          exit(0);
  133.       }
  134.       count = 0;
  135.       while((c = fgetc(fp_in)) != EOF) {
  136.          fputc(c, fp_out);
  137.          count++;
  138.       }
  139.       fclose(fp_in);
  140.       fclose(fp_out);
  141.  
  142.       if((fp_in = fopen("ram:LCrypt.tmp", "w")) == NULL)
  143.          continue;
  144.       for(k = 0; k <= count; k++)
  145.          fputc('\0', fp_in);
  146.       fclose(fp_in);
  147.       
  148.       strcpy(output, temp);
  149.       if(crypt_flag) {
  150.          output[strlen(output) - 3] = '\0';
  151.          Rename(temp, output);
  152.          printf("decrypted.\n");
  153.       }
  154.       else {
  155.          strcat(output, ".lu");
  156.          Rename(temp, output);
  157.          printf("encrypted.\n");
  158.       }
  159.    }
  160.    DeleteFile("ram:LCrypt.tmp");
  161.    printf("LCrypt finished.\n");
  162. }
  163.  
  164. useage_error()
  165. {
  166.    printf("Usage: LCrypt [de] [-directory] key filename [filename...]\n");
  167.    printf("       LCrypt ? for help.\n\n");
  168.    exit(0);
  169. }
  170.  
  171. help()
  172. {
  173.    printf("Usage: LCrypt [de] [-directory] key filename [filename...]\n\n");
  174.    printf("               d - decrypt file.\n");
  175.    printf("               e - encrypt file. [default mode]\n");
  176.    printf("      -directory - optional directory for output, include\n");
  177.    printf("                   trailing ':' or '/' for a sub-directory.\n");
  178.    printf("             key - delimit with quotes if spaces are used.\n");
  179.    printf("        filename - wildcards '?' and '*' can be used. AmigaDOS\n");
  180.    printf("                   style wildcards are not supported.\n");
  181.    exit(0);
  182. }
  183.  
  184. copy16(from, to)
  185. register BYTE *from, *to;
  186. {
  187.    register int i;
  188.    for(i = 0; i < 16; i++)
  189.       to[i] = from[i];
  190.    return;
  191. }
  192.  
  193. xor16(to, with)
  194. register BYTE *to, *with;
  195. {
  196.    register int i;
  197.    for(i = 0; i < 16; i++)
  198.       to[i] ^= with[i];
  199.    return;
  200. }
  201.  
  202. put16(block)
  203. register BYTE *block;
  204. {
  205.    if(IOedf == DE)
  206.       copy16(block, Last);
  207.    else
  208.       vraiput(block, &block[16]);
  209.    return;
  210. }
  211.  
  212. get16(input)
  213. register BYTE *input;
  214. {
  215.    register int i, j;
  216.    if(End == 1)
  217.       return(EOF);       /* no more input        */
  218.  
  219.    for(i=0; i < 16 && ((j = fgetc(fp_in)) != EOF); i++)
  220.       *input++ = j;
  221.  
  222.    if(IOedf == DE) {       /* DECRYPTION   */
  223.  
  224.       /* complete block?  pending output?     */
  225.       if(i == 16 && (Once > 0))
  226.          vraiput(Last, &Last[16]);
  227.       else if(j == EOF) {
  228.          End = 1;
  229.          if(Once > 0) {
  230.  
  231.             /* incomplete block means no nulls      */
  232.             if(i != 0)
  233.                i = 0;
  234.             else {  
  235.                i = Last[15]&0377;
  236.                if(i > 16)
  237.                   i = 0;       /* huh? */
  238.             }
  239.             vraiput(Last, &Last[16-i]);
  240.          }
  241.          return(EOF);
  242.       }
  243.    }
  244.    else if(j == EOF) {     /* ENCRYPTION   */
  245.       End = 1;
  246.       if(i == 0 && (IOedf == EN || (Once > 0))) {
  247.  
  248.          /* if no padding to do, print a kludge  */
  249.          if(IOedf == EN && (Once > 0))
  250.             fputc('0', fp_out);
  251.          return(EOF);
  252.       }
  253.       for(j=i; j < 15; j++)
  254.          *input++ = NULL;
  255.       *input = 16-i;
  256.    }
  257.    Once = 1;
  258.    return(0);
  259. }
  260.  
  261. getkey(aptr, kptr)
  262. register BYTE *aptr;
  263. register BYTE *kptr;
  264. {
  265.    register BYTE *store;
  266.    register int i, first;
  267.    BYTE hold[16];
  268.    first = 1;
  269.    loadkey(DFLTKY, EN);
  270.    copy16(DFLTKY, hold);
  271.    while(*aptr || first) {
  272.       store = kptr;
  273.       for(i=0; i<16 && (*aptr != NULL); i++) {
  274.          *store++ = toascii(*aptr);
  275.          *aptr++ = NULL;
  276.       }
  277.       while(i++ < 16)
  278.          *store++ = NULL;
  279.       xor16(kptr, hold);
  280.       lucifer(kptr);
  281.       copy16(kptr, hold);
  282.       first = 0;
  283.    }
  284.    return;
  285. }
  286.  
  287. vraiput(cp, ep)
  288. register BYTE *cp, *ep;
  289. {
  290.    while(cp < ep)
  291.       fputc((BYTE)*cp++, fp_out);
  292.    return;
  293. }
  294.  
  295. initio(edf)
  296. int edf;
  297. {
  298.    IOedf = edf;
  299.    End = Once = 0;
  300.    return;
  301. }
  302.  
  303. /* LUCIFER is a cryptographic algorithm developed by IBM in the early
  304.  *      seventies.  It was a predecessor of the DES, and is much simpler
  305.  *      than that algorithm.  In particular, it has only two substitution
  306.  *      boxes.  It does, however, use a 128 bit key and operates on
  307.  *      sixteen byte data blocks...
  308.  *
  309.  *      This implementation of LUCIFER was crafted by Graven Cyphers at the
  310.  *      University of Toronto, Canada, with programming assistance from
  311.  *      Richard Outerbridge.  It is based on the FORTRAN routines which
  312.  *      concluded Arthur Sorkin's article "LUCIFER: A Cryptographic Algorithm",
  313.  *      CRYPTOLOGIA, Volume 8, Number 1, January 1984, pp22-42.  The interested
  314.  *      reader should refer to that article rather than this program for more
  315.  *      details on LUCIFER.
  316.  *
  317.  *      These routines bear little resemblance to the actual LUCIFER algorithm,
  318.  *      which has been severely twisted in the interests of speed.  They do
  319.  *      perform the same transformations, and are believed to be UNIX portable.
  320.  *      The package was developed for use on UNIX-like systems lacking crypto
  321.  *      facilities.  They are not very fast, but the cipher is very strong.
  322.  *      The routines in this file are suitable for use as a subroutine library
  323.  *      after the fashion of crypt(3).  When linked together with applications
  324.  *      routines they can also provide a high-level cryptographic system.
  325.  *
  326.  *      -DENHANCE : modify LUCIFER by changing the key schedule and performing
  327.  *              an "autokeyed" encryption.  These may improve the algorithm.
  328.  */
  329.  
  330. static BYTE Dps[64] = { /* Diffusion Pattern schedule   */
  331.         4,16,32,2,1,8,64,128,   128,4,16,32,2,1,8,64,
  332.         64,128,4,16,32,2,1,8,   8,64,128,4,16,32,2,1,
  333.         1,8,64,128,4,16,32,2,   2,1,8,64,128,4,16,32,
  334.         32,2,1,8,64,128,4,16,   16,32,2,1,8,64,128,4    };
  335.  
  336. /* Precomputed S&P Boxes, Two Varieties */
  337.  
  338. static BYTE TCB0[256] = {
  339.         87, 21,117, 54, 23, 55, 20, 84,116,118, 22, 53, 85,119, 52, 86,
  340.         223,157,253,190,159,191,156,220,252,254,158,189,221,255,188,222,
  341.         207,141,237,174,143,175,140,204,236,238,142,173,205,239,172,206,
  342.         211,145,241,178,147,179,144,208,240,242,146,177,209,243,176,210,
  343.         215,149,245,182,151,183,148,212,244,246,150,181,213,247,180,214,
  344.         95, 29,125, 62, 31, 63, 28, 92,124,126, 30, 61, 93,127, 60, 94,
  345.         219,153,249,186,155,187,152,216,248,250,154,185,217,251,184,218,
  346.         67,  1, 97, 34,  3, 35,  0, 64, 96, 98,  2, 33, 65, 99, 32, 66,
  347.         195,129,225,162,131,163,128,192,224,226,130,161,193,227,160,194,
  348.         199,133,229,166,135,167,132,196,228,230,134,165,197,231,164,198,
  349.         203,137,233,170,139,171,136,200,232,234,138,169,201,235,168,202,
  350.         75,  9,105, 42, 11, 43,  8, 72,104,106, 10, 41, 73,107, 40, 74,
  351.         91, 25,121, 58, 27, 59, 24, 88,120,122, 26, 57, 89,123, 56, 90,
  352.         71,  5,101, 38,  7, 39,  4, 68,100,102,  6, 37, 69,103, 36, 70,
  353.         79, 13,109, 46, 15, 47, 12, 76,108,110, 14, 45, 77,111, 44, 78,
  354.         83, 17,113, 50, 19, 51, 16, 80,112,114, 18, 49, 81,115, 48, 82 };
  355.  
  356. static BYTE TCB1[256] = {
  357.         87,223,207,211,215, 95,219, 67,195,199,203, 75, 91, 71, 79, 83,
  358.         21,157,141,145,149, 29,153,  1,129,133,137,  9, 25,  5, 13, 17,
  359.         117,253,237,241,245,125,249, 97,225,229,233,105,121,101,109,113,
  360.         54,190,174,178,182, 62,186, 34,162,166,170, 42, 58, 38, 46, 50,
  361.         23,159,143,147,151, 31,155,  3,131,135,139, 11, 27,  7, 15, 19,
  362.         55,191,175,179,183, 63,187, 35,163,167,171, 43, 59, 39, 47, 51,
  363.         20,156,140,144,148, 28,152,  0,128,132,136,  8, 24,  4, 12, 16,
  364.         84,220,204,208,212, 92,216, 64,192,196,200, 72, 88, 68, 76, 80,
  365.         116,252,236,240,244,124,248, 96,224,228,232,104,120,100,108,112,
  366.         118,254,238,242,246,126,250, 98,226,230,234,106,122,102,110,114,
  367.         22,158,142,146,150, 30,154,  2,130,134,138, 10, 26,  6, 14, 18,
  368.         53,189,173,177,181, 61,185, 33,161,165,169, 41, 57, 37, 45, 49,
  369.         85,221,205,209,213, 93,217, 65,193,197,201, 73, 89, 69, 77, 81,
  370.         119,255,239,243,247,127,251, 99,227,231,235,107,123,103,111,115,
  371.         52,188,172,176,180, 60,184, 32,160,164,168, 40, 56, 36, 44, 48,
  372.         86,222,206,210,214, 94,218, 66,194,198,202, 74, 90, 70, 78, 82 };
  373.  
  374. static BYTE Key[16], Pkey[128];
  375. static int P[8] = { 3,5,0,4,2,1,7,6 };
  376. static int Smask[16] = { 128,64,32,16,8,4,2,1 };
  377.  
  378. lucifer(bytes)
  379. BYTE *bytes;    /* points to a 16-byte array    */
  380.         {
  381.         register BYTE *cp, *sp, *dp;
  382.         register int val, *sbs, tcb, j, i;
  383.         BYTE *h0, *h1, *kc, *ks;
  384.  
  385.         h0 = bytes;     /* the "lower" half     */
  386.         h1 = bytes + 8; /* the "upper" half     */
  387.         kc = Pkey;
  388.         ks = Key;
  389.  
  390.         for(i=0; i<16; i++) {
  391.                 tcb = *ks++;
  392.                 sbs = Smask;
  393.                 dp = Dps;
  394.                 sp = &h0[8];
  395.                 for(j=0; j<8; j++) {
  396.                         if(tcb&*sbs++) val = TCB1[h1[j]&0377];
  397.                         else val = TCB0[h1[j]&0377];
  398.                         val ^= *kc++;
  399.                         for(cp=h0; cp<sp;) *cp++ ^= (val&*dp++);
  400.                         }
  401.  
  402.                 /* swap (virtual) halves        */
  403.                 cp = h0;
  404.                 h0 = h1;
  405.                 h1 = cp;
  406.                 }
  407.  
  408.         /* REALLY swap halves   */
  409.         dp = bytes;
  410.         cp = bytes + 8;
  411.         for(sp=cp; dp<sp; dp++, cp++) {
  412.                 val = *dp;
  413.                 *dp = *cp;
  414.                 *cp = val;
  415.                 }
  416.         return;
  417.         } 
  418.  
  419. loadkey(keystr, edf)       /* precomputes the key schedules        */
  420. BYTE *keystr;
  421. register int edf;
  422.         {
  423.         register BYTE *ep, *cp, *pp;
  424.         register int kc, i, j;
  425.         BYTE kk[16], pk[16];
  426.         cp = kk;
  427.         pp = pk;
  428.         ep = &kk[16];
  429.         while(cp < ep) {
  430.                 *cp++ = *keystr;
  431.                 for(*pp=i=0; i<8; i++)
  432.                         if(*keystr&Smask[i]) *pp |= Smask[P[i]];
  433.                 keystr++;
  434.                 pp++;
  435.                 }
  436.         cp = Key;
  437.         pp = Pkey;
  438.         kc = (edf == DE) ? 8 : 0;
  439.         for(i=0; i<16; i++) {
  440.                 if(edf == DE) kc = (++kc)&017;
  441.                 *cp++ = kk[kc];
  442.                 for(j=0; j<8; j++) {
  443.                         *pp++ = pk[kc];
  444.                         if(j<7 || (edf == DE)) kc = (++kc)&017;
  445.                         }
  446.                 }
  447.         return;
  448.         }
  449.