So I've got a program that takes an encrypted file and essentially decrypts it.
I am now trying to modify this file.
During the encrypting process, the words were scrambled by position. The location of each word is marked with a position value.
I decrypted the original text, so now I have the plain text.
In addition, I have the .drm file from which this plain text was deciphered, and I have alice's drm file encrypted using her password.
I want to decrypt alice's .drm. I know that it has the same plaintext as my own. Since she has the same plain text as I do, I know that each word in her plain text is in the same position in the plain text as my own.
Anywho. The first thing that I need to do is take the plaintext that I decrypted and reinsert the position values in front of each word.
I then need to xor this with alice's .drm in order to obtain her keystream.
I need help with these last latter two steps.

I marked off the text where I am trying to read the words from the plain text file and then XOR them with alice's .drm file.

... I also used C++ syntax. I couldn't get c to work, but C++ is close enough

/*
 * getc(f): returns a byte of data from file f (EOF means end of file)
 * putchar(c): displays a byte (char) onto the screen
 * fopen("filename", "r"): opens "filename" for reading
 * fclose(f): closes file f
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

struct WordCatch{
   char word[1000];
   int lineno;
   int position;
};

void wSort(struct WordCatch[], int, int);

int main(int argc, char **argv)
{
  struct WordCatch words[256];
  unsigned char S[256];
  unsigned char K[256];
  unsigned char A[256];  // Alice's generated keystream
  char buffer1[100];
  char buffer2[10];
  char passwd[] = "5ne10nemo";
  char temp[2];
  int c, i, j, k, t, N, x, y, n;
  int wordCount = 0;
  int lineCount = 1;
  int beginning, ending, current;
  FILE *f, *a;

  if(argc != 3)
  {
    printf("Usage: %s <YOUdrmFile> <ALICEdrmFile> \n", argv[0]);
    return 1;
  }

  /* File = argv[1] */
  if((f = fopen(argv[1], "r")) == NULL)
  {
    printf("Error opening %s\n", argv[1]);
    return 1;
  }

  /* Password = argv[2] */
  if((a = fopen(argv[2], "r")) == NULL){
     printf("Error opening %s\n", argv[2]);
     return 1;
  }

  N = strlen(passwd);
  for(i = 0; i < 256; i++)
  {
    S[i] = i;
    K[i] = (unsigned char) passwd[i % N];
  }

  j = 0;
  for(i = 0; i < 256; i++)
  {
    j = (j + S[i] + K[i]) & 0xFF;
    t = S[i];
    S[i] = S[j];
    S[j] = t;
    words[i].word[0] = '\0';
    words[i].lineno = -1;
    words[i].position = -1;
  }

  i = j = 0;

  for (k = 100; k > 1; k--){
     //putchar('\n');
  }

  do
  {
    c = getc(f);
    if(c == 0)
    {
      k++;
      if((c = getc(f)) == EOF)
        break;
    }

    words[wordCount].lineno = k;
    words[wordCount].position = c;
    //printf("[%d, %d]", k, c);

    while((c = getc(f)) != EOF)
    {
      i = (i + 1) & 0xFF;
      j = (j + S[i]) & 0xFF;
      t = S[i];
      S[i] = S[j];
      S[j] = t;
      t = (S[i] + S[j]) & 0xFF;
      c = c ^ S[t];
      temp[0] = c;
      temp[1] = '\0';
      strncat(words[wordCount].word, temp, 1);
      //putchar(c);
      if(c == ' ' || c == '\n'){
	 wordCount++;
	 //printf("Word %d: %s\n", wordCount-1, words[wordCount-1].word);
        break;
      }
    }
  } while(c != EOF);
  fclose(f);

  /*for(i=0;i<256;i++){
     printf("(%d, %d) %s\n", words[i].lineno, words[i].position, words[i].word);
     }*/


  words[wordCount].lineno = k+1;
  wordCount++;
  lineCount = 1;
  current = 0;
  beginning = 0;
  ending = wordCount;
  
  //printf("Word count: %d\n", wordCount);

  i = j = 0;
-----------------------------------------------------------------------------------
  do
  {
     y = n = 0;
     c = getc(a);
     if(c == 0){
	lineCount++;
	if((c = getc(a)) == EOF)
	   break;
     }

     while((c = getc(a)) != EOF){
	if(isdigit(c)){
	   x = c;
	   if(isdigit(c = getc(a)))
	      x = x*10 + c;
	}

	printf("X: %d\n", x);[/B]
	
	// look for word in plain text
	while(words[y].lineno <= lineCount){
	   if(words[y++].position == x)
	      break;
	}

	A[i++] = c ^ words[y].word[n++];
     }
  } while(c != EOF);
  fclose(f);
     
  for(i = 0; i < 256; i++){
     printf("A[%d]: %s\n", i, A[i]);
  }
------------------------------------------------------------

  // Sort words in word array by line
  /*for(lineCount = 1; lineCount < 20; lineCount++){
     for(i = current; i < wordCount; i++){
	beginning = current;
	if(words[i].lineno > lineCount){
	      ending = i;
	      //printf("lineno: %d\n", words[i].lineno);
	      wSort(words, beginning, ending);
	      current = i;
	      break;
	}
     }
     }


  for(i=0; i<wordCount; i++){
     if(words[i].lineno != -1){
	//printf("(%d, %d) %s", words[i].lineno, words[i].position, words[i].word);
	printf("%s", words[i].word);
     }
     }*/
  
}

void wSort(struct WordCatch words[], int beg, int end){
   int i;
   //printf("Beg: (%d) End: (%d)\n", beg, end);
   for(i=beg; i < end; i++){
      struct WordCatch temp;
      int j, min;
      min = i;
      for(j = i+1; j < end; j++){
	 if(words[j].position <= words[min].position)
	    min = j;
      }

      temp = words[i];
      words[i] = words[min];
      words[min] = temp;
   }
   return;
}

Recommended Answers

All 5 Replies

struct WordCatch words[256];
  unsigned char S[256];
  unsigned char K[256];
  unsigned char A[256];  // Alice's generated keystream
  char buffer1[100];
  char buffer2[10];
  char passwd[] = "5ne10nemo";
  char temp[2];
  int c, i, j, k, t, N, x, y, n;
  int wordCount = 0;
  int lineCount = 1;
  int beginning, ending, current;
  FILE *f, *a;

24 variables! Usually that indicates the need for more functions. It would be easier to read with function names, too.

I heavily commented the code. It should be much more understandable now.
so we are basically focusing on lines 122 to 163

/*
 * getc(f): returns a byte of data from file f (EOF means end of file)
 * putchar(c): displays a byte (char) onto the screen
 * fopen("filename", "r"): opens "filename" for reading
 * fclose(f): closes file f
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

struct WordCatch{        ////This structure is used to store all of the words in the plain text.
                         //// Each word contains an attribute that tells its position (literally how many words it is into the sentence)
                         //// and an attribute that tracks the line number that it appears on.
   char word[1000];
   int lineno;
   int position;
};

void wSort(struct WordCatch[], int, int);        ////This function was used to sort the decyphered text by position so that each word is in its proper position.

int main(int argc, char **argv)
{
  struct WordCatch words[256];
  unsigned char S[256];   // The S boxes that are used in the RC4 algorithm
  unsigned char K[256];   //  The keystream that the RC4 algorithm generates using the password and the S boxes.
  unsigned char A[256];  // Alice's generated keystream
  char buffer1[100];
  char buffer2[10];
  char passwd[] = "5ne10nemo";     ///our password that was used to make our encrypted .drm file
  char temp[2];
  int c, i, j, k, t, N, x, y, n;
  int wordCount = 0;
  int lineCount = 1;
  int beginning, ending, current;
  FILE *f, *a;

/////////////////////// Enclosed used to obtain your .drm and alice's .drm from the user.
///////  Don't worry about it.

  if(argc != 3)   //Error message used in case a user enter's input improperly.
  {
    printf("Usage: %s <YOUdrmFile> <ALICEdrmFile> \n", argv[0]);
    return 1;
  }

  if((f = fopen(argv[1], "r")) == NULL)       /// My .drm
  {
    printf("Error opening %s\n", argv[1]);
    return 1;
  }

  if((a = fopen(argv[2], "r")) == NULL){       // Alice's .drm
     printf("Error opening %s\n", argv[2]);
     return 1;
  }
///////////////////////////////////

/// A slightly modified version of the RC4 encrypt scheme enclosed.  
/// We modified it to gather the position and line number values which were previously used to decrypt the plaintext.
///  It might not make sense that this code is still included because we have already found the plain text and stored it in a file.
//// however, we have kept the code because it stores all of the position and line number values in an array and simple makes life easier.
  N = strlen(passwd);           
  for(i = 0; i < 256; i++)
  {
    S[i] = i;
    K[i] = (unsigned char) passwd[i % N];
  }

  j = 0;
  for(i = 0; i < 256; i++)
  {
    j = (j + S[i] + K[i]) & 0xFF;
    t = S[i];
    S[i] = S[j];
    S[j] = t;
    words[i].word[0] = '\0';
    words[i].lineno = -1;
    words[i].position = -1;
  }

  i = j = 0;

  for (k = 100; k > 1; k--){
  }

  do
  {
    c = getc(f);
    if(c == 0)
    {
      k++;
      if((c = getc(f)) == EOF)
        break;
    }

    words[wordCount].lineno = k;
    words[wordCount].position = c;

    while((c = getc(f)) != EOF)
    {
      i = (i + 1) & 0xFF;
      j = (j + S[i]) & 0xFF;
      t = S[i];
      S[i] = S[j];
      S[j] = t;
      t = (S[i] + S[j]) & 0xFF;
      c = c ^ S[t];
      temp[0] = c;
      temp[1] = '\0';
      strncat(words[wordCount].word, temp, 1);
      if(c == ' ' || c == '\n'){
	 wordCount++;
        break;
      }
    }
  } while(c != EOF);
  fclose(f);
////////////////////////////////  end of rc4 algorithm

///////  This is the stuff we care about.
  words[wordCount].lineno = k+1;
  wordCount++;
  lineCount = 1;
  current = 0;
  beginning = 0;
  ending = wordCount;

  i = j = 0;

  do
  {
     y = n = 0;
     c = getc(a);
     if(c == 0){
	lineCount++;
	if((c = getc(a)) == EOF)
	   break;
     }

     while((c = getc(a)) != EOF){
	if(isdigit(c)){
	   x = c;
	   if(isdigit(c = getc(a)))
	      x = x*10 + c;
	}

	printf("X: %d\n", x);
	
	// look for word in plain text
	while(words[y].lineno <= lineCount){
	   if(words[y++].position == x)
	      break;
	}

	A[i++] = c ^ words[y].word[n++];
     }
  } while(c != EOF);
  fclose(f);
     
  for(i = 0; i < 256; i++){
     printf("A[%d]: %s\n", i, A[i]);
  }

///All of the below code was originally used for decrypting purposes.  It is no longer necessary.

  // Sort words in word array by line
  /*for(lineCount = 1; lineCount < 20; lineCount++){
     for(i = current; i < wordCount; i++){
	beginning = current;
	if(words[i].lineno > lineCount){
	      ending = i;
	      //printf("lineno: %d\n", words[i].lineno);
	      wSort(words, beginning, ending);
	      current = i;
	      break;
	}
     }
     }


  for(i=0; i<wordCount; i++){
     if(words[i].lineno != -1){
	//printf("(%d, %d) %s", words[i].lineno, words[i].position, words[i].word);
	printf("%s", words[i].word);
     }
     }

void wSort(struct WordCatch words[], int beg, int end){   ////This function takes all of the position attributes of each word and puts the words in order.  It works properly.
   int i;
   for(i=beg; i < end; i++){
      struct WordCatch temp;
      int j, min;
      min = i;
      for(j = i+1; j < end; j++){
	 if(words[j].position <= words[min].position)
	    min = j;
      }

      temp = words[i];
      words[i] = words[min];
      words[min] = temp;
   }
   return;
}
*/

Breaking a program into functions helps you to think about it, forcing you to name parts and parameters and think in a hierarchical instead of a linear manner. Here's a version of your program broken into functions.

The code compiles but I have no data to run it with (nor a clear enough understanding of your data structure to create test data). It should perform (or not) about the same as your old code. (But note the comments beginning with //! .)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


typedef unsigned char uchar;

// This structure is used to store all of the words in the plain text.
// Each word contains an attribute that tells its position (literally
// how many words it is into the sentence)
// and an attribute that tracks the line number that it appears on.
struct Word {
   char word[1000];  //! Should be dynamically allocated?
   int lineno;
   int position;
};


void wSort(struct Word*, int, int);
int myrc4(FILE *f, char *passwd, struct Word *words);
void myrc4_init(struct Word *words, char *passwd, uchar *S, uchar *K);
void calc_keystream(FILE *a, struct Word *words, int wordCount, uchar *A);


int main(int argc, char **argv)
{
  FILE *f, *a;
  struct Word words[256];
  int wordCount = 0;
  uchar A[256];  // Alice's generated keystream
  char passwd[] = "5ne10nemo"; // password used to make encrypted .drm file

  if(argc != 3) // Check command line args.
  {
    printf("Usage: %s <YOUdrmFile> <ALICEdrmFile> \n", argv[0]);
    return 1;
  }

  //! Should maybe be opening these in binary mode?
  //! (Only makes a difference on some systems, but does
  //!  document that it is (probably) not a text file.)
  //! Actually, maybe f is a text file and a is a binary file?

  if((f = fopen(argv[1], "r")) == NULL)       /// My .drm
  {
    printf("Error opening %s\n", argv[1]);
    return 1;
  }

  if((a = fopen(argv[2], "r")) == NULL){       // Alice's .drm
     printf("Error opening %s\n", argv[2]);
     return 1;
  }

  wordCount = myrc4(f, passwd, words);

  calc_keystream(a, words, wordCount, A);

  //! A is a uchar array, not a string array,
  //! so I changed the spec from %s to $c.
  //! You may want to check for unprintable chars.
  {
    int i;
    for(i = 0; i < 256; i++)
       printf("A[%d]: %c\n", i, A[i]);
  }

  return 0;
}

///////////////////////////////////
// A slightly modified version of the RC4 encrypt scheme enclosed.
// We modified it to gather the position and line number values
// which were previously used to decrypt the plaintext.
// It might not make sense that this code is still included
// because we have already found the plain text and stored it
// in a file.
// however, we have kept the code because it stores all of the
// position and line number values in an array and simple makes
// life easier.

int myrc4(FILE *f, char *passwd, struct Word *words){

  uchar S[256];     // The S boxes that are used in the RC4 algorithm.
  uchar K[256];     // The keystream that the RC4 algorithm generates
                    // using the password and the S boxes.
  int lineCnt = 1;
  int i = 0, j = 0, c;
  int wordCount = 0;

  myrc4_init (words, passwd, S, K);

  //! This processing is very shaky.
  //! It looks like it cannot deal with any extra spaces.

  do
  {
    c = getc(f);

    if(c == 0) //! Shouldn't you be testing for '\n' in the plaintext?
    {
      lineCnt++;

      if((c = getc(f)) == EOF)
        break;
    }

    words[wordCount].lineno = lineCnt;
    words[wordCount].position = c;

    while((c = getc(f)) != EOF)
    {
      int t;
      i = (i + 1) & 0xFF;
      j = (j + S[i]) & 0xFF;
      t = S[i]; S[i] = S[j]; S[j] = t;
      t = (S[i] + S[j]) & 0xFF;
      c = c ^ S[t];

//! This will not zero-terminate word.
//!      temp[0] = c;
//!      temp[1] = '\0';
//!      strncat(words[wordCount].word, temp, 1);
//! This will (and avoids the function call).
      words[wordCount].word[0] = c;
      words[wordCount].word[1] = '\0';

      if(c == ' ' || c == '\n'){
        wordCount++;
        break;
      }
    }
  } while(c != EOF);
  fclose(f);

  //! Not sure if I "translated" this bit properly.
  words[wordCount++].lineno = ++lineCnt;

  return wordCount;
}

void myrc4_init(struct Word *words, char *passwd, uchar *S, uchar *K){

  int i, j;
  int N = strlen(passwd);

  for(i = 0; i < 256; i++)
  {
    S[i] = i;
    K[i] = (uchar) passwd[i % N];
  }

  for(i = 0, j = 0; i < 256; i++)
  {
    int t;
    j = (j + S[i] + K[i]) & 0xFF;
    t = S[i]; S[i] = S[j]; S[j] = t;
    words[i].word[0] = '\0';
    words[i].lineno = -1;
    words[i].position = -1;
  }
}

void calc_keystream(FILE *a, struct Word *words, int wordCount, uchar *A){

  int lineCount = 1;
  int current = 0;
  int x, y, n, c;
  int i = 0, j = 0;

  do
  {
    y = n = 0;
    c = getc(a);
    if(c == 0){
      lineCount++;
      if((c = getc(a)) == EOF)
        break;
    }

    while((c = getc(a)) != EOF){
      if(isdigit(c)){
        x = c;
        if(isdigit(c = getc(a)))
          x = x*10 + c;
      }

      printf("X: %d\n", x);

      // look for word in plain text
      while(words[y].lineno <= lineCount){
        if(words[y++].position == x)
          break;
      }

      A[i++] = c ^ words[y].word[n++];
    }
  } while(c != EOF);

  fclose(a);   //! Was fclose(f)
}

// BELOW THIS LINE: Unused in current incarnation of program.

void sort_words(struct Word *words, int wordCount){
  int beginning = 0;
  int ending = wordCount + 1;
  int current = 0;
  int lineCount, i;
  // Sort words in word array by line
  for(lineCount = 1; lineCount < 20; lineCount++){
    for(i = current; i < wordCount; i++){
      beginning = current;
      if(words[i].lineno > lineCount){
        ending = i;
        //printf("lineno: %d\n", words[i].lineno);
        wSort(words, beginning, ending);
        current = i;
        break;
      }
    }
  }
}

void display_words(struct Word *words, int wordCount){
  int i;
  for(i=0; i<wordCount; i++){
    if(words[i].lineno != -1){
      //printf("(%d, %d) %s", words[i].lineno, words[i].position, words[i].word);
      printf("%s", words[i].word);
    }
  }
}

// This function takes all of the position attributes of each word and puts
// the words in order.  It works properly.
void wSort(struct Word *words, int beg, int end){
   int i;
   for(i=beg; i < end; i++){
      struct Word temp;
      int j, min;
      min = i;
      for(j = i+1; j < end; j++){
	 if(words[j].position <= words[min].position)
	    min = j;
      }
      temp = words[i];
      words[i] = words[min];
      words[min] = temp;
   }
   return;
}

wish you'd use tag for syntax highlighting. much easier to read.[code=c] tag for syntax highlighting. much easier to read.

Good point. I'll try to remember to do that. The line numbers can be useful to. Can't edit it now, though. :(

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.