Sign in to follow this  

Simple Encryption Gone Awry [solved]

This topic is 3300 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

It's been a long while since I posted here, but I have a bit of a problem on my hands, and I'm stumped as to how to solve it. It's in a program I have named the "Generic Encryption Program," a simple, command-line XOR-based encryption program that I've been working on for a while now in VC++ 2008 Express. My problem is is that it successfully encrypts the file, but when I check the file, it's size doesn't match the source file; the source file being 4kb in size, and the encrypted file being only 4 bytes in size. Also, when I exit, it gives me these errors: First-chance exception at 0x7c911e5a in GEP.exe: 0xC0000005: Access violation reading location 0x616d6d73. First-chance exception at 0x7c90eb74 in GEP.exe: 0xC0000008: An invalid handle was specified. First-chance exception at 0x7c9118c5 in GEP.exe: 0xC0000005: Access violation reading location 0x7079726b. Unhandled exception at 0x7c9118c5 in GEP.exe: 0xC0000005: Access violation reading location 0x7079726b. The code for the Encrypt() function is as follows:
void Encrypt(string file_loc, string destination, string dest_filename)
{
  string true_dest; // The real destination, with filename
  
  system("cls"); // Clear the console of old text.
  
  cout << "Generating true destination...\n";

  true_dest += destination + dest_filename + ".RH0";

  cout << "True destination generated...\n";
  
  ifstream in_file;
  ofstream out_file;
  
  cout << "Generating file streams...\n";

  in_file.open(file_loc.c_str(), ios::in | ios::binary);
  
  if (!in_file.is_open())
  {
    cout << "Error in opening input file, exiting...\n" << endl;
    
    system("PAUSE");
    system("EXIT");
  }
  out_file.open(true_dest.c_str(), ios::out | ios::binary | ios::app);
  
  if (!out_file.is_open())
  {
    cout << "Error in opening output (*.RH0) file, exiting...\n" << endl;
    
    system("PAUSE");
    system("EXIT");
  }
  
  cout << "File stream generation successful..." << endl;

  long long size;
  size = sizeof(in_file);
  char* file_mem = new char;
  
  in_file.read(file_mem, size);
  
  // Encryption begins here, XOR by 128.
  
  for (int i = 0; i < sizeof(file_mem); i++)
  {
    char xor_byte = file_mem[i] ^ 128;
    out_file << xor_byte;
  }  
  
  // Encryption ends here.
  
  in_file.close();
  out_file.close();
  
  cout << "Encrypted file generated at location: " << true_dest.c_str();
  cout << endl << endl;

  system("PAUSE");
  system("EXIT");
}
The access violations always point me to the last "}" at the end of the function, so that's of no help... Anyone have any ideas as to what I may be doing wrong? [Edited by - RavynousHunter on December 5, 2008 6:45:47 AM]

Share this post


Link to post
Share on other sites
There are at least two problems in your code.

First is - you are incorrectly getting size of file. sizeof() operator will return size of variable, not what it contains. So sizeof(in_file) will return constant something like 144 (depending on your compiler). If you want to get size of file then seekg to end of file and use tellg to get current position in file.

Second problem is - you are allocating only 1 byte of memory (new char), but reading into memory a lot more bytes (size count). If you want to allocate more bytes then you should use new char [count_of_bytes] syntax. Or better - use std::vector<char> which will automaticaly manage memory for you.

Share this post


Link to post
Share on other sites
Thanks for the reply, however, I now get another error. VC++ tells me in the in_file.read(file_mem, size) line that I need to convert file_mem from a std::vector<char> to a char*, but I see no methods within the vector itself to do so.

I might be able to use a for loop to insert the file into memory byte by byte, but which method should I use to read each byte should I decide to use this approach?

Share this post


Link to post
Share on other sites
http://www.cplusplus.com/reference/iostream/istream/read.html

Read() excepts array. File_mem is not an array, but a pointer to one byte. If you want to read only one byte at once, you have to set size to 1 or use get().

Share this post


Link to post
Share on other sites
The problem is, is that I'm no longer using an array (and that method caused problems, as well), but am using a vector, which gives me this error:


gep.cpp(147) : error C2664: 'std::basic_istream<_Elem,_Traits>::read' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'char *'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
and
[
_Ty=char
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called


Could I use one of the cast functions (like static_cast, or dynamic_cast) to temporarily cast file_mem as a generic character array?

Share this post


Link to post
Share on other sites
You might be able to do &file_mem[0], which should get you a pointer to the start of the vectors memory, you'd have to make sure that the vector is already at a sufficient size to cover the data your going to read into it though, otherwise you'll overwrite memory that belongs to something else.

Share this post


Link to post
Share on other sites
I would even go as far as suggesting...

void encrypt(const char* in_filename,
const char* out_filename)
{
std::ifstream in(in_filename, ios::in | ios::binary);
std::ofstream out(out_filename, ios::out | ios::binary | ios::app);
if (in && out)
std::transform(std::istream_iterator<char>(in),
std::istream_iterator<char>(),
std::ostream_iterator<char>(out),
xor);
}

char xor(char c)
{
return c ^ 128;
}

Share this post


Link to post
Share on other sites
If you want a potato (an array), you shouldn't try to use a pile of carrots (a vector) instead.

Read() has been designed for potatoes, so you should create a potato and pass it as a parameter instead of painting carrots brown and passing them.

int array_size = 10;
char buffer[array_size];
in_file.read(buffer, array_size);


It is as simple as that, where is problem?

Share this post


Link to post
Share on other sites
you might notice that people give you constantly hints how to solve a specific error.

my hint to you is that you just seem to dont know how to program and miss the understanding of fundamental knowdledge. i recommend reading a good book about
c++. i cannot understand why you might write an encryption program without
knowing how to parse a file in c/c++, so i am assuming you are a beginner in coding.

regards,
cal

Share this post


Link to post
Share on other sites
It's not a matter of not having the knowledge, it's just that I'm a bit rusty with my file streams and whatnot. I haven't been programming much because my primary computer which had all of my utilities and whatnot went south, and I get a limited amount of time on the other two, seeing as how they belong to other people.

Anyway, the problem has been resolved, my program works without a hitch now.

PS: It may just be me, calav3ra, but that comment comes off as a bit condescending.

Share this post


Link to post
Share on other sites
Quote:
Original post by ville-v
If you want a potato (an array), you shouldn't try to use a pile of carrots (a vector) instead.


The OP does not want an array. In C++, arrays have a fixed size - determined at compile time. The OP wants a dynamic container, which is exactly what a vector is.

Or a solution like Toohrvyk provided.

Share this post


Link to post
Share on other sites
Quote:
Original post by ville-v
If you want a potato (an array), you shouldn't try to use a pile of carrots (a vector) instead.

Read() has been designed for potatoes, so you should create a potato and pass it as a parameter instead of painting carrots brown and passing them.

*** Source Snippet Removed ***

It is as simple as that, where is problem?
For starters, that's not even valid C++, it's probably a gcc specific extension because it's only valid in C99 iirc, which isn't particularly widely supported. The fact that you then can't pass that buffer out of the function containing the array is a pretty big limitation as well. That's not a problem if you pass in a vector by reference.
Passing the address of the first element of a vector is the correct C++ way to do it, and someone who hasn't heard of that before probably isn't very experienced in C++. grekster, you can be a lot more sure of yourself next time you suggest this, it's what everyone does and it is guaranteed to work (as long as you ensure the size is sufficient beforehand).

Share this post


Link to post
Share on other sites

This topic is 3300 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this