home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / wvnsc926 / wvcrypt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  10.1 KB  |  350 lines

  1. /*--- wvcrypt.c -- Simple encryption routines for WinVN.
  2.  *
  3.  *  These simple encryption/decryption routines are used to
  4.  *  protect the user's NNTP server password.
  5.  *  The lack of sophistication is meant to protect the
  6.  *  exportability of this code.    For better stuff, see the
  7.  *  non-anonymous FTP site ripem.msu.edu.
  8.  */
  9.  
  10. /*
  11.  * $Id: wvcrypt.c 1.4 1994/05/26 22:58:38 jglasser Exp $
  12.  */
  13.  
  14. #include <time.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17.  
  18. /* #define DEBUG 1 */
  19.  
  20. #define ROTORSIZE 256
  21. #define NSEEDBYTES 4
  22. #define RANBUFSIZE 15
  23. #define RANLAG1     9
  24. #define RANLAG2     14
  25.  
  26. static unsigned char RanbufMaster[RANBUFSIZE] = {
  27.     0, 0, 0, 0, 56, 34, 199, 77, 245, 252, 17, 184, 130, 215, 102 };
  28. static unsigned char *Ranbuf;
  29. static Ranidx;
  30.  
  31. void MRRMakeRotors(unsigned char *ranbuf, unsigned char *rotorE,
  32.  unsigned char *rotorD);
  33. int MRRRan(unsigned char *Ranbuf);
  34. int prencode (unsigned char *bufin , unsigned int nbytes , char *bufcoded );
  35. int prdecode (char *bufcoded , unsigned char *bufplain , int outbufsize );
  36.  
  37.  
  38.  
  39. /*--- function MRREncrypt ------------------------------------------
  40.  *
  41.  *  Encrypt and printably encode a sequence of bytes.
  42.  *
  43.  *  Entry:    plainText    is the input plaintext (binary bytes).
  44.  *             len            is the number of bytes in the above.
  45.  *             cipherText    is an output buffer that must be
  46.  *                             2*len+6 bytes long.
  47.  *
  48.  *  Exit:    cipherText    is a zero-terminated ASCII printable
  49.  *                             string of ciphertext.
  50.  */
  51. void
  52. MRREncrypt(unsigned char *plainText,int len,char *cipherText)
  53. {
  54.     time_t mytime;
  55.     int j;
  56.     unsigned char prev=0;
  57.     unsigned char *cipbuf, *cipbuforig;
  58.     unsigned char ranbuf[RANBUFSIZE], rotorE[ROTORSIZE], rotorD[ROTORSIZE];
  59.  
  60.     if(!len) {
  61.         cipherText[0] = '\0';
  62.         return;
  63.     }
  64.     cipbuf = cipbuforig = malloc (len+4);
  65.  
  66.     time(&mytime);
  67.     memcpy(ranbuf,RanbufMaster,RANBUFSIZE);
  68.     for(j=0; j<NSEEDBYTES; j++) {
  69.         cipbuf[j] = ranbuf[j] = (unsigned char) (mytime & 0xff);
  70.         mytime >>= 8;
  71.     }
  72.  
  73.     MRRMakeRotors(ranbuf,rotorE, rotorD);
  74.  
  75.     for(j=0; j<len; j++) {
  76.         cipbuf[j+NSEEDBYTES] = prev = rotorE[(*(plainText++)+prev)%ROTORSIZE];
  77.     }
  78.  
  79.     prencode(cipbuf,len+NSEEDBYTES,cipherText);
  80.     free(cipbuforig);
  81. }
  82.  
  83. int
  84. MRRDecrypt(char *cipherText,unsigned char *plainText, int plainMax)
  85. {
  86.     unsigned char prev=0;
  87.     unsigned char *cipbuf, *cipbuforig;
  88.     unsigned char ranbuf[RANBUFSIZE], rotorE[ROTORSIZE], rotorD[ROTORSIZE];
  89.     int j, nbytes, ch;
  90.  
  91.     if(!strlen(cipherText)) {
  92.         plainText[0] = '\0';
  93.         return 0;
  94.     }
  95.  
  96.     cipbuf = cipbuforig = malloc(plainMax+4);
  97.  
  98.     nbytes = prdecode(cipherText,cipbuf,plainMax) - NSEEDBYTES;
  99.     memcpy(ranbuf,RanbufMaster,RANBUFSIZE);
  100.     memcpy(ranbuf,cipbuf,NSEEDBYTES);
  101.     MRRMakeRotors(ranbuf,rotorE, rotorD);
  102.  
  103.     cipbuf += NSEEDBYTES;
  104.     for(j=0; j<nbytes; j++) {
  105.         ch = (int)rotorD[*cipbuf] - (int)prev;
  106.         if(ch < 0) ch += ROTORSIZE;
  107.         prev = *cipbuf;
  108.         *(plainText++) = ch;
  109.         cipbuf++;
  110.     }
  111.  
  112.     free(cipbuforig);
  113.     return nbytes;
  114. }
  115.  
  116.  
  117. /*--- function MRRMakeRotors -----------------------------------------
  118.  *
  119.  *  Set up the rotors used for encryption/decryption.
  120.  *
  121.  *  Entry:    Ranbuf is a buffer of "random" bytes.
  122.  *
  123.  *  Exit:    rotorE and rotorD are the encryption and
  124.  *             corresponding decryption rotors.
  125.  */
  126. void
  127. MRRMakeRotors(unsigned char *ranbuf, unsigned char *rotorE,
  128.  unsigned char *rotorD)
  129. {
  130.     int j, k, idx;
  131.     unsigned char ch;
  132.  
  133.     /* Make a standard reflexive rotor. */
  134.     for(j=0; j<ROTORSIZE; j++) {
  135.         rotorE[j] = j;
  136.     }
  137.     Ranidx = 0;
  138.  
  139.     /* Permute the rotor */
  140.     for(k=2; k; k--) for(j=ROTORSIZE-1; j; j--) {
  141.         idx = MRRRan(ranbuf);
  142.         /* This code omitted: idx = idx%(j+1); */
  143.         ch = rotorE[j];
  144.         rotorE[j] = rotorE[idx];
  145.         rotorE[idx] = ch;
  146.     }
  147.  
  148.     /* Create rotorD as the inverse of rotorE */
  149.     for(j=0; j<ROTORSIZE; j++) {
  150.         rotorD[rotorE[j]] = j;
  151.     }
  152.  
  153. #ifdef DEBUGMRR
  154.     printf("rotorE:\n");
  155.     for(j=0; j<ROTORSIZE; j++) {
  156.         printf("%4d",rotorE[j]);
  157.         if((j+1)%16 == 0) printf("\n");
  158.     }
  159.     printf("rotorD:\n");
  160.     for(j=0; j<ROTORSIZE; j++) {
  161.         printf("%4d",rotorD[j]);
  162.         if((j+1)%16 == 0) printf("\n");
  163.     }
  164. #endif
  165. }
  166.  
  167. /*--- function MRRRan --------------------------------------------------
  168.  *
  169.  *  Return a pseudorandom number in the range 0-255.
  170.  *  Uses an additive linear shift register.
  171.  *
  172.  *  Entry:    Ranbuf    is a buffer of RANBUFSIZE random bytes.
  173.  *             Ranidx    is an index into this buffer.
  174.  *
  175.  *  Exit:    Ranidx has been decremented.
  176.  *             Returns the next pseudorandom number.
  177.  */
  178. int
  179. MRRRan(unsigned char *Ranbuf)
  180. {
  181.     int idx1, idx2;
  182.  
  183.     if(--Ranidx < 0) Ranidx = RANBUFSIZE-1;
  184.     idx1 = Ranidx+RANLAG1;
  185.     if(idx1>=RANBUFSIZE) idx1 -= RANBUFSIZE;
  186.     idx2 = Ranidx+RANLAG2;
  187.     if(idx2>=RANBUFSIZE) idx2 -= RANBUFSIZE;
  188.  
  189.     Ranbuf[Ranidx] = 0xff & (Ranbuf[idx1] + Ranbuf[idx2] + Ranbuf[Ranidx]);
  190.  
  191.     return Ranbuf[Ranidx];
  192. }
  193.  
  194.  
  195. /*--- prencode.c -- File containing routines to convert a buffer
  196.  *  of bytes to/from RFC 1113 printable encoding format.
  197.  *
  198.  *  This technique is similar to the familiar Unix uuencode
  199.  *  format in that it maps 6 binary bits to one ASCII
  200.  *  character (or more aptly, 3 binary bytes to 4 ASCII
  201.  *  characters).  However, RFC 1113 does not use the same
  202.  *  mapping to printable characters as uuencode.
  203.  *
  204.  *  Mark Riordan   12 August 1990 and 17 Feb 1991.
  205.  *  This code is hereby placed in the public domain.
  206.  */
  207.  
  208.  
  209. static char six2pr[64] = {
  210. 'A','B','C','D','E','F','G','H','I','J','K','L','M',
  211. 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  212. 'a','b','c','d','e','f','g','h','i','j','k','l','m',
  213. 'n','o','p','q','r','s','t','u','v','w','x','y','z',
  214. '0','1','2','3','4','5','6','7','8','9','+','/'        };
  215.  
  216. /*--- function prencode -----------------------------------------------
  217.  *
  218.  *   Encode a single line of binary data to a standard format that
  219.  *   uses only printing ASCII characters (but takes up 33% more bytes).
  220.  *
  221.  *    Entry    bufin    points to a buffer of bytes.  If nbytes is not
  222.  *                      a multiple of three, then the byte just beyond
  223.  *                      the last byte in the buffer must be 0.
  224.  *             nbytes   is the number of bytes in that buffer.
  225.  *             bufcoded points to an output buffer.  Be sure that this
  226.  *                      can hold at least 1 + (4*nbytes)/3 characters.
  227.  *
  228.  *    Exit     bufcoded contains the coded line.  The first 4*nbytes/3 bytes
  229.  *                      contain printing ASCII characters representing
  230.  *                      those binary bytes. This may include one or
  231.  *                      two '=' characters used as padding at the end.
  232.  *                      The last byte is a zero byte.
  233.  *             Returns the number of ASCII characters in "bufcoded".
  234.  */
  235. int
  236. prencode(bufin, nbytes, bufcoded)
  237. unsigned char *bufin;
  238. unsigned int nbytes;
  239. char *bufcoded;
  240. {
  241. /* ENC is the basic 1 character encoding function to make a char printing */
  242. #define ENC(c) six2pr[c]
  243.  
  244.    register char *outptr = bufcoded;
  245.    unsigned int i;
  246.  
  247.    for (i=0; i<nbytes; i += 3) {
  248.       *(outptr++) = ENC(*bufin >> 2);            /* c1 */
  249.       *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017));  /* c2 */
  250.       *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /* c3 */
  251.       *(outptr++) = ENC(bufin[2] & 077);         /* c4 */
  252.  
  253.       bufin += 3;
  254.    }
  255.  
  256.    /* If nbytes was not a multiple of 3, then we have encoded too
  257.     * many characters.  Adjust appropriately.
  258.     */
  259.    if(i == nbytes+1) {
  260.       /* There were only 2 bytes in that last group */
  261.       outptr[-1] = '=';
  262.    } else if(i == nbytes+2) {
  263.       /* There was only 1 byte in that last group */
  264.       outptr[-1] = '=';
  265.       outptr[-2] = '=';
  266.    }
  267.    *outptr = '\0';
  268.    return(outptr - bufcoded);
  269. }
  270.  
  271. /*--- function prdecode ------------------------------------------------
  272.  *
  273.  *  Decode an ASCII-encoded buffer back to its original binary form.
  274.  *
  275.  *     Entry     bufcoded     points to a encoded string.    It is
  276.  *                         terminated by any character not in
  277.  *                         the printable character table six2pr, but
  278.  *                         leading whitespace is stripped.
  279.  *             bufplain    points to the output buffer; must be big
  280.  *                         enough to hold the decoded string (generally
  281.  *                         shorter than the encoded string) plus
  282.  *                         as many as two extra bytes used during
  283.  *                         the decoding process.
  284.  *             outbufsize  is the maximum number of bytes that
  285.  *                         can fit in bufplain.
  286.  *
  287.  *    Exit     Returns the number of binary bytes decoded.
  288.  *             bufplain    contains these bytes.
  289.  */
  290. int
  291. prdecode(bufcoded,bufplain,outbufsize)
  292. char *bufcoded;
  293. unsigned char *bufplain;
  294. int outbufsize;
  295. {
  296. /* single character decode */
  297. #define DEC(c) pr2six[(int)c]
  298. #define MAXVAL 63
  299.  
  300.    int nbytesdecoded, j;
  301.    register char *bufin = bufcoded;
  302.    register unsigned char *bufout = bufplain;
  303.    register int nprbytes;
  304.     unsigned char pr2six[256];
  305.  
  306.  
  307.     /* Initialize the mapping table.
  308.     * This code should work even on non-ASCII machines.
  309.     */
  310.     for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
  311.  
  312.     for(j=0; j<64; j++) pr2six[(int)six2pr[j]] = (unsigned char) j;
  313.  
  314.    /* Strip leading whitespace. */
  315.  
  316.    while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
  317.  
  318.    /* Figure out how many characters are in the input buffer.
  319.     * If this would decode into more bytes than would fit into
  320.     * the output buffer, adjust the number of input bytes downwards.
  321.     */
  322.    bufin = bufcoded;
  323.    while(pr2six[(int)*(bufin++)] <= MAXVAL);
  324.    nprbytes = bufin - bufcoded - 1;
  325.    nbytesdecoded = ((nprbytes+3)/4) * 3;
  326.    if(nbytesdecoded > outbufsize) {
  327.       nprbytes = (outbufsize*4)/3;
  328.    }
  329.  
  330.    bufin = bufcoded;
  331.    
  332.    while (nprbytes > 0) {
  333.       *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
  334.       *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
  335.       *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
  336.       bufin += 4;
  337.       nprbytes -= 4;
  338.    }
  339.    
  340.    if(nprbytes & 03) {
  341.       if(pr2six[(int)bufin[-2]] > MAXVAL) {
  342.          nbytesdecoded -= 2;
  343.       } else {
  344.          nbytesdecoded -= 1;
  345.       }
  346.    }
  347.  
  348.    return(nbytesdecoded);
  349. }
  350.