First, you had a subtle problem:
Code:
std::string XOR(std::string line, std::string key)
{
unsigned int i = 0, j = 0;
std::size_t l_length, k_length;
std::string e_line;
l_length = line.length();
k_length = key.length();
for(;i < l_length; i++, j++)
{
e_line.push_back(line[i] ^ key[j]);
if(j == k_length)
{
j = 0;
}
}
/* Return the encrypted line */
return e_line;
}
The problem is you increment
j and use it with the key as an index to encrypt the string,
then you check and make sure it's within bounds. The bounds check should be
before you use it, so try this instead:
Code:
std::string XOR(std::string line, std::string key)
{
unsigned int i = 0, j = 0;
std::size_t l_length, k_length;
std::string e_line;
l_length = line.length();
k_length = key.length();
for(;i < l_length; i++, j++)
{
if(j == k_length)
{
j = 0;
}
e_line.push_back(line[i] ^ key[j]);
}
/* Return the encrypted line */
return e_line;
}
Now the main event. That's a problem with the way you are doing the encryption/decryption using
getline.
getline looks for a trailing newline character (or end of file) and then stops. When you first encrypt your string, the
getline successfully reads the whole string and the 'o' in "work!" happens to get encrypted as a ASCII value 10 which is either a carriage return or line feed (I forget which). When it comes time to decrypt the string,
getline stops at that character prematurely (extracts and throws away). Because of this, a second
getline call is needed to read and decrypt the rest of the file. Since your encrypt/decrypt method works on whole lines, this second round of decryption starts using the wrong key index and the wrong cypher text character from what was used in the encryption step. Bottom line here is I don't think you should be using
getline when doing something like this. Getting the characters one-by-one or getting all the characters at once (using an intermediate
stringstream object and
rdbuf) and then encrypting them with the key might be best here.
I'd do something like this for the reading instead of the
while loop and
getline calls:
Code:
#include <sstream>
...
std::stringstream sstr;
sstr << inputfile.rdbuf(); // Read whole file in one go, no loop needed
line = sstr.str(); // Convert stringstream to string
line = XOR(line, key);
outputfile << line;