
/************************************************************************/
/*  BMB                                                                 */
/*                                                                      */
/*        CMSC443                                                       */
/*                                                                      */
/*                                                                      */
/*     This program implements the encryption and decryption by         */
/*   Linear Feedback Shift Register project.  The user enters the       */
/*   number of bits the shift register should contain, the taps, and    */
/*   the starting fill.  When given plaintext, the program converts     */
/*   it to ciphertext, and when given ciphertext, the program converts  */
/*   it to plaintext, since both are accomplished by XOR with the key.  */
/*                                                                      */
/*      In this program the register shifts to the left -- that is, the */
/*   leftmost bit "falls off" the register and becomes the next bit of  */
/*   key, and then the new bit comes into the rightmost bit of the      */
/*   register.                                                          */
/*                                                                      */
/*      The program will take no more than 100,000 characters from the  */
/*   input file, but this can easily be modified by changing the        */
/*   definition of the constant MAXCHARS.                               */
/*                                                                      */
/*      To run this program, the usage line should be:                  */
/*                                                                      */
/*   a.out <inputfilename> <outputfilename>                             */
/*                                                                      */
/*   I received no help in writing this project.                        */
/************************************************************************/

#include <stdio.h>
#define MAXCHARS 100000

/* All variables are global so as not to have to pass them to functions. */

int Regsize;      /* The number of bits in the shift register. */
int Register;     /* The fill of the register, initialized by user input. */
int Taps;         /* The bits to be tapped, entered by user in decimal form. */
int Count;        /* Which character is being worked on. */
int i, j, k;      /* Placeholder variables */
int Temp, Newbit; /* For running the shift register. */

char ch;               /* For reading from the input file. */
char Plain[MAXCHARS];  /* To store the characters in the input file. */
char Key[MAXCHARS];    /* To store the bits of the key before XORing. */
char Cipher[MAXCHARS]; /* To store the characters in the output file. */

/* This function actually performs the en/decryption with information
    passed to it from main. */
void Encrypt(char *, char *);

main(int argc, char *argv[])
    {
    if(argc!=3)
      {
      printf("Usage: a.out infile outfile");
      exit(0);
      }

/* Get all the information from the user. */

    printf("Enter the number of bits in the register.");
    scanf("%d", &Regsize);

    printf("Enter the taps in decimal.");
    scanf("%d", &Taps);

    printf("Enter the starting seed of the register in decimal.");
    scanf("%d", &Register);

    /* Send the information from the user to the Encrypt function. */

    Encrypt(argv[1], argv[2]);
      
}

void Encrypt(char *infilename, char *outfilename)
{
FILE *plaintext, *ciphertext;

/* Read in the plaintext file. */

if( (plaintext = fopen(infilename, "r")) == NULL)
  {
  printf("Couldn't open plaintext file for reading.");
  exit(0);
  }

/* This variable will keep track of the number of characters to be
    en/decrypted, so as not to waste time, up to a maximum of MAXCHARS. */
Count=0;

while( (fscanf(plaintext, "%c", &ch)) != EOF)
     {
     if(Count>MAXCHARS)break;
     Plain[Count]=ch;
     Count++;
     }

if( fclose(plaintext) != 0)
  {
  printf("Error in closing files.");
  exit(0);
  }

/* The plaintext characters have been read into the Plain array. */
/* Count holds the effective size of the input file, in characters. */

/* Run the register to en/decrypt characters of the input file. */

for(i=0; i<Count; i++)     /* Get a key for each character. */
    for(j=0; j<8; j++)    /* There will be 8 bits in each character's key. */
       {
       /* Left-shift the key to make room for the next bit. */
       Key[i] <<= 1;      

       /* Put the next bit of key from the register fill into that slot. */
       Key[i] ^= ( ( Register >> (Regsize - 1) ) &1 );

       /* Now shift the register once. */

       /* Read off the bits which are to be tapped. */
       Temp = Register & Taps;

       /* Left-shift the register one bit. */
       Register <<= 1;
    
       /* Form the new bit which will come in on the right of the register. */
       /* Newbit will become that bit; it starts out as zero. */
       Newbit=0;

       /* Then it becomes the XOR sum of all the tapped bits. */
       for(k=0; k<Regsize; k++)
          Newbit ^= ( ( Temp & (1 << k) ) >> k ) ;
    
       /* Put the new bit into the rightmost register bit. */
       Register ^= Newbit;

       /* Finally, mask off only those bits of the register which are needed.
          As in, if the register size is eight, only the rightmost eight
           bits of the register should be saved.  (This is equivalent to
           "dumping off" that bit which fell off the left to become a key
           bit.
       */
       Register &= ( (1<<Regsize) - 1);
       }

/* Now the Key array has been filled with the bits from the shift register. */

/* It is time to form the Cipher array from the key and the Plain array. */

for(i=0; i<Count; i++)
   Cipher[i] = Plain[i] ^ Key[i];

/* Write the results to the output file. */

if( (ciphertext = fopen(outfilename, "w")) == NULL)
  {
  printf("Couldn't open output file.");
  exit(0);
  }

for(i=0; i<Count; i++)
   putc(Cipher[i], ciphertext);

if( fclose(ciphertext) != 0 )
  {
  printf("Error in closing the output file.");
  exit(0);
  }

}




