home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / CRYPT.C < prev    next >
C/C++ Source or Header  |  1991-03-12  |  8KB  |  234 lines

  1. /*    Crypt:    Encryption routines for MicroEMACS
  2.         written by Dana Hoggatt and Daniel Lawrence
  3. */
  4.  
  5. #include    <stdio.h>
  6. #include    "estruct.h"
  7. #include    "eproto.h"
  8. #include    "edef.h"
  9. #include    "elang.h"
  10.  
  11. #if    CRYPT
  12. static int mod95();
  13.  
  14. PASCAL NEAR setekey(f, n)    /* reset encryption key of current buffer */
  15.  
  16. int f;        /* default flag */
  17. int n;        /* numeric argument */
  18.  
  19. {
  20.     register int status;    /* return status */
  21.     int odisinp;        /* original vlaue of disinp */
  22.     char key[NPAT];        /* new encryption string */
  23.  
  24.     /* turn command input echo off */
  25.     odisinp = disinp;
  26.     disinp = FALSE;
  27.  
  28.     /* get the string to use as an encrytion string */
  29.     status = mlreply(TEXT33, key, NPAT - 1);
  30. /*                       "Encryption String: " */
  31.     disinp = odisinp;
  32.         if (status != TRUE)
  33.                 return(status);
  34.  
  35.     /* and encrypt it */
  36.     crypt((char *)NULL, (unsigned int) 0);
  37.     crypt(key, (unsigned int) strlen(key));
  38.  
  39.     /* and save it off */
  40.     strcpy(curbp->b_key, key);
  41.     mlwrite(" ");        /* clear it off the bottom line */
  42.     return(TRUE);
  43. }
  44.  
  45. /**********
  46.  *
  47.  *    crypt - in place encryption/decryption of a buffer
  48.  *
  49.  *    (C) Copyright 1986, Dana L. Hoggatt
  50.  *    1216, Beck Lane, Lafayette, IN
  51.  *
  52.  *    When consulting directly with the author of this routine, 
  53.  *    please refer to this routine as the "DLH-POLY-86-B CIPHER".  
  54.  *
  55.  *    This routine was written for Dan Lawrence, for use in V3.8 of
  56.  *    MicroEMACS, a public domain text/program editor.  
  57.  *
  58.  *    I kept the following goals in mind when preparing this function:
  59.  *
  60.  *        1.    All printable characters were to be encrypted back
  61.  *        into the printable range, control characters and
  62.  *        high-bit characters were to remain unaffected.  this
  63.  *        way, encrypted would still be just as cheap to 
  64.  *        transmit down a 7-bit data path as they were before.
  65.  *
  66.  *        2.    The encryption had to be portable.  The encrypted 
  67.  *        file from one computer should be able to be decrypted 
  68.  *        on another computer.
  69.  *
  70.  *        3.    The encryption had to be inexpensive, both in terms
  71.  *        of speed and space.
  72.  *
  73.  *        4.    The system needed to be secure against all but the
  74.  *        most determined of attackers.
  75.  *
  76.  *    For encryption of a block of data, one calls crypt passing 
  77.  *    a pointer to the data block and its length. The data block is 
  78.  *    encrypted in place, that is, the encrypted output overwrites 
  79.  *    the input.  Decryption is totally isomorphic, and is performed 
  80.  *    in the same manner by the same routine.  
  81.  *
  82.  *    Before using this routine for encrypting data, you are expected 
  83.  *    to specify an encryption key.  This key is an arbitrary string,
  84.  *    to be supplied by the user.  To set the key takes two calls to 
  85.  *    crypt().  First, you call 
  86.  *
  87.  *        crypt(NULL, vector)
  88.  *
  89.  *    This resets all internal control information.  Typically (and 
  90.  *    specifically in the case on MICRO-emacs) you would use a "vector" 
  91.  *    of 0.  Other values can be used to customize your editor to be 
  92.  *    "incompatable" with the normally distributed version.  For 
  93.  *    this purpose, the best results will be obtained by avoiding
  94.  *    multiples of 95.
  95.  *
  96.  *    Then, you "encrypt" your password by calling 
  97.  *
  98.  *        crypt(pass, strlen(pass))
  99.  *
  100.  *    where "pass" is your password string.  Crypt() will destroy 
  101.  *    the original copy of the password (it becomes encrypted), 
  102.  *    which is good.  You do not want someone on a multiuser system 
  103.  *    to peruse your memory space and bump into your password.  
  104.  *    Still, it is a better idea to erase the password buffer to 
  105.  *    defeat memory perusal by a more technical snooper.  
  106.  *
  107.  *    For the interest of cryptologists, at the heart of this 
  108.  *    function is a Beaufort Cipher.  The cipher alphabet is the 
  109.  *    range of printable characters (' ' to '~'), all "control" 
  110.  *    and "high-bit" characters are left unaltered.
  111.  *
  112.  *    The key is a variant autokey, derived from a wieghted sum 
  113.  *    of all the previous clear text and cipher text.  A counter 
  114.  *    is used as salt to obiterate any simple cyclic behavior 
  115.  *    from the clear text, and key feedback is used to assure 
  116.  *    that the entire message is based on the original key, 
  117.  *    preventing attacks on the last part of the message as if 
  118.  *    it were a pure autokey system.
  119.  *
  120.  *    Overall security of encrypted data depends upon three 
  121.  *    factors:  the fundamental cryptographic system must be 
  122.  *    difficult to compromise; exhaustive searching of the key 
  123.  *    space must be computationally expensive; keys and plaintext 
  124.  *    must remain out of sight.  This system satisfies this set
  125.  *    of conditions to within the degree desired for MicroEMACS.
  126.  *
  127.  *    Though direct methods of attack (against systems such as 
  128.  *    this) do exist, they are not well known and will consume 
  129.  *    considerable amounts of computing time.  An exhaustive
  130.  *    search requires over a billion investigations, on average.
  131.  *
  132.  *    The choice, entry, storage, manipulation, alteration, 
  133.  *    protection and security of the keys themselves are the 
  134.  *    responsiblity of the user.  
  135.  *
  136.  **********/
  137.  
  138. PASCAL NEAR crypt(bptr, len)
  139. register char *bptr;    /* buffer of characters to be encrypted */
  140. register unsigned len;    /* number of characters in the buffer */
  141. {
  142.     register int cc;    /* current character being considered */
  143.  
  144.     static long key = 0;    /* 29 bit encipherment key */
  145.     static int salt = 0;    /* salt to spice up key with */
  146.  
  147.     if (!bptr) {        /* is there anything here to encrypt? */
  148.         key = len;    /* set the new key */
  149.         salt = len;    /* set the new salt */
  150.         return;
  151.     }
  152.     while (len--) {        /* for every character in the buffer */
  153.  
  154.         cc = *bptr;    /* get a character out of the buffer */
  155.  
  156.         /* only encipher printable characters */
  157.         if ((cc >= ' ') && (cc <= '~')) {
  158.  
  159. /*    We feed the upper few bits of the key back into itself. This assures us
  160.     that the starting key affects the entire message. We go through some
  161.     effort here to prevent the key from exceeding 29 bits.  This is so the
  162.     aritmetic caluclation in a later statement, which impliments our
  163.     autokey, won't overflow, making the key go negative. Machine behavior
  164.     in these cases does not tend to be portable.    */
  165.  
  166.             if (oldcrypt) {
  167.                 key &= 0x1FFFFFFFL;    /* strip off overflow */
  168.                 if (key & 0x10000000L) {
  169.                     key ^= 0x0040A001L;    /* feedback */
  170.                 }
  171.             } else
  172.                 key = (key & 0x1FFFFFFFl) ^ ((key >> 29) & 0x3l);
  173.  
  174. /**  Down-bias the character, perform a Beaufort encipherment, and 
  175.     up-bias the character again.  We want key to be positive 
  176.     so that the left shift here will be more portable and the 
  177.     mod95() faster   **/
  178.  
  179.             cc = mod95((int)(key % 95) - (cc - ' ')) + ' ';
  180.  
  181. /**  the salt will spice up the key a little bit, helping to obscure 
  182.     any patterns in the clear text, particularly when all the 
  183.     characters (or long sequences of them) are the same.  We do 
  184.     not want the salt to go negative, or it will affect the key 
  185.     too radically.  It is always a good idea to chop off cyclics 
  186.     to prime values.  **/
  187.  
  188.             if (++salt >= 20857) {    /* prime modulus */
  189.                 salt = 0;
  190.             }
  191.  
  192. /**  our autokey (a special case of the running key) is being 
  193.     generated by a weighted checksum of clear text, cipher 
  194.     text, and salt.
  195.  
  196.     I had to allow the older broken key calculation to let us decrypt
  197.     old files.  I hope to take this out eventually. **/
  198.  
  199.             if (oldcrypt)
  200.                 key = key + key + cc + *bptr + salt;
  201.             else
  202.                 key = key + key + (cc ^ *bptr) + salt;
  203.         }
  204.         *bptr++ = cc;    /* put character back into buffer */
  205.     }
  206.     return;
  207. }
  208.  
  209. static int mod95(val)
  210.  
  211. register int val;
  212.  
  213. {
  214.     /*  The mathematical MOD does not match the computer MOD  */
  215.  
  216.     /*  Yes, what I do here may look strange, but it gets the
  217.         job done, and portably at that.  */
  218.  
  219.     while (val >= 9500)
  220.         val -= 9500;
  221.     while (val >= 950)
  222.         val -= 950;
  223.     while (val >= 95)
  224.         val -= 95;
  225.     while (val < 0)
  226.         val += 95;
  227.     return (val);
  228. }
  229. #else
  230. nocrypt()
  231. {
  232. }
  233. #endif
  234.