MrWhite
MrWhite

Reputation: 189

C++ XOR encryption - decryption issue

I followed a tutorial on stephan-brumme website for XOR encryption (unfortunately I cannot include URL because I do not have enough reputation). What I want to do is following: read the content of example.txt file and decrypt the text that it includes. For example, this is the content of example.txt:

\xe7\xfb\xe0\xe0\xe7

This, when decrypted using password "password" should return "hello". This is the code I got:

#include <string>
#include <iostream>
#include <fstream>

using namespace std;

std::string decode(const std::string& input)
{
  const size_t passwordLength = 9;
  static const char password[passwordLength] = "password";
  std::string result = input;
  for (size_t i = 0; i < input.length(); i++)
    result[i] ^= ~password[i % passwordLength];
  return result;
}

int main(int argc, char* argv[])
{
  string line;
  ifstream myfile ("example.txt");
  if (myfile.is_open())
  {
    while ( getline (myfile,line) )
    {
      cout << decode(line);
    }
    myfile.close();
  }

  return 0;
}

And this is the result of running the application: click for image

As you can see, the decryption was not successful. Now, if I make it so it doesn't read the .txt, but directly decrypts the text, like this:

cout << decode("\xe7\xfb\xe0\xe0\xe7");

It works perfectly: click for image

What am I doing wrong here?

Many thanks in advance! :)

Upvotes: 1

Views: 2025

Answers (2)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

Character XOR by same character is zero, so the result may include zero. std::string doesn't like that because zero terminates the string.

You also can use std::vector<char> instead of std::string for the actual encoding/decoding. You would have to change the decode function to handle vector<char>

And read/write the file in binary.

Edit: Using std::string only, and std::string decode(const std::string& input)

int main()
{
    std::string line = "hello";

    {
        line = decode(line);
        std::ofstream myfile("example.txt", std::ios::binary);
        myfile.write(line.data(), line.size());

        //Edit 2 *************
        //std::cout << std::hex;
        //for (char c : line)
        //  std::cout << "\\x" << (0xff & c);
        //*************
        //This will make sure width is always 2
        //For example, it will print "\x01\x02" instead of "\x1\x2"
        std::cout << std::hex << std::setfill('0');
        for (char c : line)
            std::cout << "\\x" << std::setw(2) << (0xff & c);
        std::cout << std::endl;
    }

    {
        std::ifstream myfile("example.txt", std::ios::binary | std::ios::ate);
        int filesize = (int)myfile.tellg();
        line.resize(filesize);
        myfile.seekg(0);
        myfile.read(&line[0], filesize);
        line = decode(line);
        std::cout << line << std::endl;
    }

    return 0;
}

Upvotes: 1

I bet example.txt contains the characters '\', 'x', 'e', '7' etc. You have to read those, process all the backslash escapes, and then feed it to decode.

\xe7 is a common way of representing a single character with hex value E7. (Which is quite likely to be the single character 'ç' depending on your character set). If you want to store (encrypted) readable text, I suggest dropping the \x, and having the file contain lines like "e7fbe0e0e7". Then - read each line into a string. - Convert each pair of characters from a hex number into an integer, and store the result in a char. - Store that char in the string. - Then xor decrypt the string.

Alternatively, ensure the file contains the actual binary characters you need it to.

Also beware that you are XOR-ing with the terminating nul byte of the password. Did you mean to do that?

Upvotes: 1

Related Questions