home *** CD-ROM | disk | FTP | other *** search
- /*--- wvcrypt.c -- Simple encryption routines for WinVN.
- *
- * These simple encryption/decryption routines are used to
- * protect the user's NNTP server password.
- * The lack of sophistication is meant to protect the
- * exportability of this code. For better stuff, see the
- * non-anonymous FTP site ripem.msu.edu.
- */
-
- /*
- * $Id: wvcrypt.c 1.4 1994/05/26 22:58:38 jglasser Exp $
- */
-
- #include <time.h>
- #include <string.h>
- #include <stdlib.h>
-
- /* #define DEBUG 1 */
-
- #define ROTORSIZE 256
- #define NSEEDBYTES 4
- #define RANBUFSIZE 15
- #define RANLAG1 9
- #define RANLAG2 14
-
- static unsigned char RanbufMaster[RANBUFSIZE] = {
- 0, 0, 0, 0, 56, 34, 199, 77, 245, 252, 17, 184, 130, 215, 102 };
- static unsigned char *Ranbuf;
- static Ranidx;
-
- void MRRMakeRotors(unsigned char *ranbuf, unsigned char *rotorE,
- unsigned char *rotorD);
- int MRRRan(unsigned char *Ranbuf);
- int prencode (unsigned char *bufin , unsigned int nbytes , char *bufcoded );
- int prdecode (char *bufcoded , unsigned char *bufplain , int outbufsize );
-
-
-
- /*--- function MRREncrypt ------------------------------------------
- *
- * Encrypt and printably encode a sequence of bytes.
- *
- * Entry: plainText is the input plaintext (binary bytes).
- * len is the number of bytes in the above.
- * cipherText is an output buffer that must be
- * 2*len+6 bytes long.
- *
- * Exit: cipherText is a zero-terminated ASCII printable
- * string of ciphertext.
- */
- void
- MRREncrypt(unsigned char *plainText,int len,char *cipherText)
- {
- time_t mytime;
- int j;
- unsigned char prev=0;
- unsigned char *cipbuf, *cipbuforig;
- unsigned char ranbuf[RANBUFSIZE], rotorE[ROTORSIZE], rotorD[ROTORSIZE];
-
- if(!len) {
- cipherText[0] = '\0';
- return;
- }
- cipbuf = cipbuforig = malloc (len+4);
-
- time(&mytime);
- memcpy(ranbuf,RanbufMaster,RANBUFSIZE);
- for(j=0; j<NSEEDBYTES; j++) {
- cipbuf[j] = ranbuf[j] = (unsigned char) (mytime & 0xff);
- mytime >>= 8;
- }
-
- MRRMakeRotors(ranbuf,rotorE, rotorD);
-
- for(j=0; j<len; j++) {
- cipbuf[j+NSEEDBYTES] = prev = rotorE[(*(plainText++)+prev)%ROTORSIZE];
- }
-
- prencode(cipbuf,len+NSEEDBYTES,cipherText);
- free(cipbuforig);
- }
-
- int
- MRRDecrypt(char *cipherText,unsigned char *plainText, int plainMax)
- {
- unsigned char prev=0;
- unsigned char *cipbuf, *cipbuforig;
- unsigned char ranbuf[RANBUFSIZE], rotorE[ROTORSIZE], rotorD[ROTORSIZE];
- int j, nbytes, ch;
-
- if(!strlen(cipherText)) {
- plainText[0] = '\0';
- return 0;
- }
-
- cipbuf = cipbuforig = malloc(plainMax+4);
-
- nbytes = prdecode(cipherText,cipbuf,plainMax) - NSEEDBYTES;
- memcpy(ranbuf,RanbufMaster,RANBUFSIZE);
- memcpy(ranbuf,cipbuf,NSEEDBYTES);
- MRRMakeRotors(ranbuf,rotorE, rotorD);
-
- cipbuf += NSEEDBYTES;
- for(j=0; j<nbytes; j++) {
- ch = (int)rotorD[*cipbuf] - (int)prev;
- if(ch < 0) ch += ROTORSIZE;
- prev = *cipbuf;
- *(plainText++) = ch;
- cipbuf++;
- }
-
- free(cipbuforig);
- return nbytes;
- }
-
-
- /*--- function MRRMakeRotors -----------------------------------------
- *
- * Set up the rotors used for encryption/decryption.
- *
- * Entry: Ranbuf is a buffer of "random" bytes.
- *
- * Exit: rotorE and rotorD are the encryption and
- * corresponding decryption rotors.
- */
- void
- MRRMakeRotors(unsigned char *ranbuf, unsigned char *rotorE,
- unsigned char *rotorD)
- {
- int j, k, idx;
- unsigned char ch;
-
- /* Make a standard reflexive rotor. */
- for(j=0; j<ROTORSIZE; j++) {
- rotorE[j] = j;
- }
- Ranidx = 0;
-
- /* Permute the rotor */
- for(k=2; k; k--) for(j=ROTORSIZE-1; j; j--) {
- idx = MRRRan(ranbuf);
- /* This code omitted: idx = idx%(j+1); */
- ch = rotorE[j];
- rotorE[j] = rotorE[idx];
- rotorE[idx] = ch;
- }
-
- /* Create rotorD as the inverse of rotorE */
- for(j=0; j<ROTORSIZE; j++) {
- rotorD[rotorE[j]] = j;
- }
-
- #ifdef DEBUGMRR
- printf("rotorE:\n");
- for(j=0; j<ROTORSIZE; j++) {
- printf("%4d",rotorE[j]);
- if((j+1)%16 == 0) printf("\n");
- }
- printf("rotorD:\n");
- for(j=0; j<ROTORSIZE; j++) {
- printf("%4d",rotorD[j]);
- if((j+1)%16 == 0) printf("\n");
- }
- #endif
- }
-
- /*--- function MRRRan --------------------------------------------------
- *
- * Return a pseudorandom number in the range 0-255.
- * Uses an additive linear shift register.
- *
- * Entry: Ranbuf is a buffer of RANBUFSIZE random bytes.
- * Ranidx is an index into this buffer.
- *
- * Exit: Ranidx has been decremented.
- * Returns the next pseudorandom number.
- */
- int
- MRRRan(unsigned char *Ranbuf)
- {
- int idx1, idx2;
-
- if(--Ranidx < 0) Ranidx = RANBUFSIZE-1;
- idx1 = Ranidx+RANLAG1;
- if(idx1>=RANBUFSIZE) idx1 -= RANBUFSIZE;
- idx2 = Ranidx+RANLAG2;
- if(idx2>=RANBUFSIZE) idx2 -= RANBUFSIZE;
-
- Ranbuf[Ranidx] = 0xff & (Ranbuf[idx1] + Ranbuf[idx2] + Ranbuf[Ranidx]);
-
- return Ranbuf[Ranidx];
- }
-
-
- /*--- prencode.c -- File containing routines to convert a buffer
- * of bytes to/from RFC 1113 printable encoding format.
- *
- * This technique is similar to the familiar Unix uuencode
- * format in that it maps 6 binary bits to one ASCII
- * character (or more aptly, 3 binary bytes to 4 ASCII
- * characters). However, RFC 1113 does not use the same
- * mapping to printable characters as uuencode.
- *
- * Mark Riordan 12 August 1990 and 17 Feb 1991.
- * This code is hereby placed in the public domain.
- */
-
-
- static char six2pr[64] = {
- 'A','B','C','D','E','F','G','H','I','J','K','L','M',
- 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
- 'a','b','c','d','e','f','g','h','i','j','k','l','m',
- 'n','o','p','q','r','s','t','u','v','w','x','y','z',
- '0','1','2','3','4','5','6','7','8','9','+','/' };
-
- /*--- function prencode -----------------------------------------------
- *
- * Encode a single line of binary data to a standard format that
- * uses only printing ASCII characters (but takes up 33% more bytes).
- *
- * Entry bufin points to a buffer of bytes. If nbytes is not
- * a multiple of three, then the byte just beyond
- * the last byte in the buffer must be 0.
- * nbytes is the number of bytes in that buffer.
- * bufcoded points to an output buffer. Be sure that this
- * can hold at least 1 + (4*nbytes)/3 characters.
- *
- * Exit bufcoded contains the coded line. The first 4*nbytes/3 bytes
- * contain printing ASCII characters representing
- * those binary bytes. This may include one or
- * two '=' characters used as padding at the end.
- * The last byte is a zero byte.
- * Returns the number of ASCII characters in "bufcoded".
- */
- int
- prencode(bufin, nbytes, bufcoded)
- unsigned char *bufin;
- unsigned int nbytes;
- char *bufcoded;
- {
- /* ENC is the basic 1 character encoding function to make a char printing */
- #define ENC(c) six2pr[c]
-
- register char *outptr = bufcoded;
- unsigned int i;
-
- for (i=0; i<nbytes; i += 3) {
- *(outptr++) = ENC(*bufin >> 2); /* c1 */
- *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /* c2 */
- *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /* c3 */
- *(outptr++) = ENC(bufin[2] & 077); /* c4 */
-
- bufin += 3;
- }
-
- /* If nbytes was not a multiple of 3, then we have encoded too
- * many characters. Adjust appropriately.
- */
- if(i == nbytes+1) {
- /* There were only 2 bytes in that last group */
- outptr[-1] = '=';
- } else if(i == nbytes+2) {
- /* There was only 1 byte in that last group */
- outptr[-1] = '=';
- outptr[-2] = '=';
- }
- *outptr = '\0';
- return(outptr - bufcoded);
- }
-
- /*--- function prdecode ------------------------------------------------
- *
- * Decode an ASCII-encoded buffer back to its original binary form.
- *
- * Entry bufcoded points to a encoded string. It is
- * terminated by any character not in
- * the printable character table six2pr, but
- * leading whitespace is stripped.
- * bufplain points to the output buffer; must be big
- * enough to hold the decoded string (generally
- * shorter than the encoded string) plus
- * as many as two extra bytes used during
- * the decoding process.
- * outbufsize is the maximum number of bytes that
- * can fit in bufplain.
- *
- * Exit Returns the number of binary bytes decoded.
- * bufplain contains these bytes.
- */
- int
- prdecode(bufcoded,bufplain,outbufsize)
- char *bufcoded;
- unsigned char *bufplain;
- int outbufsize;
- {
- /* single character decode */
- #define DEC(c) pr2six[(int)c]
- #define MAXVAL 63
-
- int nbytesdecoded, j;
- register char *bufin = bufcoded;
- register unsigned char *bufout = bufplain;
- register int nprbytes;
- unsigned char pr2six[256];
-
-
- /* Initialize the mapping table.
- * This code should work even on non-ASCII machines.
- */
- for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
-
- for(j=0; j<64; j++) pr2six[(int)six2pr[j]] = (unsigned char) j;
-
- /* Strip leading whitespace. */
-
- while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
-
- /* Figure out how many characters are in the input buffer.
- * If this would decode into more bytes than would fit into
- * the output buffer, adjust the number of input bytes downwards.
- */
- bufin = bufcoded;
- while(pr2six[(int)*(bufin++)] <= MAXVAL);
- nprbytes = bufin - bufcoded - 1;
- nbytesdecoded = ((nprbytes+3)/4) * 3;
- if(nbytesdecoded > outbufsize) {
- nprbytes = (outbufsize*4)/3;
- }
-
- bufin = bufcoded;
-
- while (nprbytes > 0) {
- *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
- *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
- *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
- bufin += 4;
- nprbytes -= 4;
- }
-
- if(nprbytes & 03) {
- if(pr2six[(int)bufin[-2]] > MAXVAL) {
- nbytesdecoded -= 2;
- } else {
- nbytesdecoded -= 1;
- }
- }
-
- return(nbytesdecoded);
- }
-