I am learning c++, below is an attempt at a simple XOR encryption program. I am am using Dev c++ (Blooodshed Ide) using the ming-gw win 32 gcc compiler blah blah.

This code compiles without errors or warnings but it will not produce an 'exe' only a '.o' file, firstly what is a '.o' file? Without much ado I am guessing its a type of report produced when the program contains run-time errors. I am unable to access it though :o(

secondly does anyone know how this code could run; without having to make too many extreme changes to it?

Thanks S

#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>



    using namespace std;
    string textToEncrypt;
    string outString;
    
    int main(int argc, char* argv[])
    {
         int key = 129;         
         fstream infile1;
         infile1.open(argv[0],ios::in);//Open file
         infile1 >> textToEncrypt; 
         
        {            
            char c;
            int i;
            int j = textToEncrypt.length();
            while (!infile1.eof( ))  
            {
             for (int x=0;j-1;x++){
                c = textToEncrypt[i];
                c = (char)(c ^ key);//Encypt characters using v. simple XOR
                outString[x] = c;
                i++;
                }
            }
             
        } 
        infile1.write((char*)&outString,sizeof(outString)); //Write encryption
        infile1.close();
        return 0; 
    }
infile1.open(argv[0],ios::in);//Open file

There are 2 things in your code.

The first one is argv[0] ,Try to take this(written below) example program and see what the output is like .

#include <iostream>
int main(int argc, char* argv[])
{
std::cout<<argv[0];
}

Next,
You have used ios::in which makes the fstream provide input operations. so i am pretty unsure about Writing the encryption

>This code compiles without errors or warnings but it will not produce an 'exe' only a '.o' file, firstly what is a '.o' file?
A .o file is an object file, when the compiler compiles the source code, it will generate such a file, most of the time, after the source file has been compiled the linker is directly executed/invoked thereafter, the linker will 'link' the object file to an executable file (under Windows, this file will have a .exe extension).
(Some compilers generate a .obj file instead of a .o file, just remember that they're both object files).

Also, read this and fix your code.

In addition:

You should initialize textToEncrypt with a value before asking for it's .length() . Just to be on the safe side.

Also: You should check if argv[0] has a value, before passing it to ifstream to open it.

then this : for (int x=0;j-1;x++) You're telling the compiler to :
make x=0 (x=0)
loop while j-1 is not zero (j-1)
increment x while looping (x++)

this is probably not the loop you wanted. Try to rethink it again.

And last (I'm not going to start about while (!infile1.eof( )) ....):The typecasting you're using is C, not C++. This: c = (char)(c ^ key);//Encypt characters using v. simple XOR Should be written as: c = static_cast<char>(c ^ key);//Encypt characters using v. simple XOR

Hello,
This is how I went about XOR'ing a binary file and outputting to another file the XORed contents. Does anybody see anything wrong with this approach or something I should do differently? I was able to reapply the XOR to the "encrypted" file and receive a valid jpg back from it. Compiled and ran fine on Redhat and XP. Usage
xor inputfile outputfile key

#include <iostream>
using std::ios;
using std::cout;
using std::endl;

#include <fstream>
using std::ofstream;
using std::ifstream;

int main(int argc, char *argv[])
{
  // open plaintext file
  ifstream plainFile(argv[1], ios::in | ios::ate | ios::binary);

  char *memblock;

  if (plainFile.is_open())
  {
    ifstream::pos_type size = plainFile.tellg();
    memblock = new char [size];
    plainFile.seekg(0, ios::beg);
    plainFile.read(memblock, size);
    plainFile.close();
    cout << "Plaintext file contents in memory" << endl;
    
    // create output filestream
   ofstream encryptedFile(argv[2], ios::out | ios::binary);
   cout << "XOR\'ing the buffer" << endl;
  
   // XOR the chars 
   for (int i = 0; i < size; i++)
     memblock[i] ^= *(argv[3]);
   
   // write buffer to file
   cout << "Writing to \"encrypted file\"" << endl;
   encryptedFile.write(memblock, size);

   delete [] memblock;
   plainFile.close();
   encryptedFile.close();
  }
  // error opening file
  else
    cout << "Couldn't open file" << endl;
  return 0;
}

> Does anybody see anything wrong with this approach or something I should do differently?
1. You should deal with the file in fixed sized blocks. Don't assume that you'll always be able to fit the file in memory in one go.

2. You only use the first letter of your key.

Comments
Good catches!

Hello Salem,
I'm thinking I could use atoi to convert the third arg to an int.

int key = atoi(argv[3]);
.
.
.
// XOR
for (int i=0; i<size; i++)
  memblock[i] ^= key;

How would I process the file block by block?
Could I figure out the file size, process say 100 bytes at a time, update file pointer to 100 bytes later in the file? process data again until eof is reached? If there are less than 100 bytes in last read of file, then use that amount to process? Is that right?

BTW, I like your avatar.

Also: You should check if argv[0] has a value, before passing it to ifstream to open it.

Didn't you mean argv[1] ?

BTW, I like your avatar.

Yes, he's got a nice avatar, don't steal it :P
ROFL: I've only got a Kung Fu Panda :P

Well reading a file a block at a time might be something like this.

#include <iostream>
#include <fstream>

int main ( ) {
  char buff[1000];
  std::ifstream in("a.out", std::ios::in | std::ios::binary);
  if ( in ) {
    int errorCount = 1;
    while ( in.read(buff,sizeof buff) || errorCount-- > 0 ) {
      std::streamsize n = in.gcount();
      if ( n > 0 ) {
        std::cout << "Read " << n << " bytes" << std::endl;
      }
    }
    in.close();
  }
}

I'm shocked that read() returns an error state on a partial read. The C-style fread() approach is far easier.

As for the key, you should be using some kind of counter so you do buff[i] ^= key[k]; Where k is a subscript looping over the length of the key.

This article has been dead for over six months. Start a new discussion instead.