【问题标题】:C++ XOR encryption - decryption issueC++ XOR 加密 - 解密问题
【发布时间】:2015-12-12 19:22:21
【问题描述】:

我按照 stephan-brumme 网站上的教程进行了 XOR 加密(不幸的是,我不能包含 URL,因为我没有足够的声誉)。我想要做的是:阅读 example.txt 文件的内容并解密它包含的文本。例如,这是example.txt的内容:

\xe7\xfb\xe0\xe0\xe7

当使用密码“password”解密时,应该返回“hello”。这是我得到的代码:

#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;
}

这是运行应用程序的结果: click for image

如您所见,解密不成功。现在,如果我这样做,它不会读取 .txt,而是直接解密文本,如下所示:

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

完美运行: click for image

我在这里做错了什么?

提前非常感谢! :)

【问题讨论】:

  • 最有可能的来源是 example.txt 的内容。请记住 XOR 的输出是二进制格式,这意味着 example.txt 需要是 UTF-8。为了保持一致性,请始终使用相同类型的键和输入 [例如:char 或 widechar(utf-8)]
  • example.txt 是 UTF-8。感谢您的帮助!
  • 你能附上一张显示文件内容的图片吗?
  • 当然,这里是:i.imgur.com/dzc9nBh.png
  • 从文件内容中删除“\x”,并将文件读取为ascii。

标签: c++ encryption cryptography xor


【解决方案1】:

相同字符的字符异或为零,因此结果可能包括零。 std::string 不喜欢这样,因为零会终止字符串。

您也可以使用std::vector&lt;char&gt; 而不是std::string 进行实际的编码/解码。您必须更改 decode 函数来处理 vector&lt;char&gt;

并以二进制形式读取/写入文件。

编辑:仅使用 std::stringstd::string decode(const std::string&amp; 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;
}

【讨论】:

  • std::string 可以很好地保存 NUL 字符(它的 C 字符串与 NUL 有问题),因此无需使用 vector。问题(由您解决)是getline 无法处理 NUL,而且如果换行符被加密,getline 将无法找到它们,因此您需要使用二进制读取。
  • 这工作正常,但我需要以可读的方式加密“你好”。我的意思是,我需要它像 \xe7\xfb\xe0\xe0\xe7 而不是那样:i.imgur.com/tne1I7T.png 这可能吗?非常感谢!
  • @ChrisDodd 你是对的。 std::string 有时会终止,例如当看到“abc\0123”时,当涉及到零时,我通常会远离它。但在这种情况下应该没问题。我将编辑答案以仅显示 std::string
  • 这是我遵循的教程:create.stephan-brumme.com/hide-strings-executable 是否有可能使“你好”以本教程中的格式加密而不使用不可读的符号?谢谢!
  • @MrWhite,只需格式化输出。查看更新的答案。
【解决方案2】:

我敢打赌 example.txt 包含字符 '\'、'x'、'e'、'7' 等。您必须阅读这些字符,处理所有反斜杠转义,然后 然后 提要它来解码。

\xe7 是用十六进制值 E7 表示 单个 字符的常用方法。 (这很可能是单个字符“ç”,具体取决于您的字符集)。如果你想存储(加密的)可读文本,我建议删除 \x,并让文件包含像“e7fbe0e0e7”这样的行。然后 - 将每一行读入一个字符串。 - 将每对字符从十六进制数转换为整数,并将结果存储在 char 中。 - 将该字符存储在字符串中。 - 然后对字符串进行异或解密。

或者,确保文件包含您需要的实际二进制字符。

还要注意,您正在与密码的终止 nul 字节进行异或运算。你是故意的吗?

【讨论】:

  • 我完全赞成对不好的答案投反对票 - 但请帮助我改进;告诉我什么我的回答不好。
  • 是的,它确实包含这些字符。抱歉,我不明白您所说的“处理所有反斜杠转义,然后将其提供给解码”是什么意思。你能更具体一点吗?非常感谢您的帮助!
  • \xe7 是用十六进制值 E7 表示 单个 字符的常用方法。 (这很可能是单个字符“ç”,具体取决于您的字符集)。如果您想存储(加密的)可读文本,我建议删除 \x,并让文件包含像“e7fbe0e0e7”这样的行
  • 然后,在我阅读文件后,我可以添加斜杠,它应该可以工作吗?
  • 斜线不存在。它们不是字符串中的字符。写为“\xe7\xe8”的字符串有两个字符长。正如“\r\n”是两个字符一样。另一方面,“/xe7/xe8”是八个字符长。 ...并且要让 C++ 程序用反斜杠显示这 8 个字符,您必须编写 cout
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 2010-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多