2015-12-12 51 views
1

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

\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

我在做什么错在这里?

非常感谢提前! :)

+0

最可能的来源是example.txt中的内容。记住XOR的输出是二进制格式,这意味着example.txt需要是UTF-8。为了保持一致性,请始终使用相同类型的键和输入[例如:char或widechar(utf-8)] – Nandu

+0

example.txt为UTF-8。感谢您的帮助! – MrWhite

+0

可以包含显示文件内容的图像吗? – Nandu

回答

1

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

对于实际的编码/解码,您也可以使用std::vector<char>而不是std::string。您将不得不更改decode函数以处理vector<char>

并以二进制读/写该文件。

编辑:只使用std::string,并且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; 
} 
+0

'std :: string'可以容纳NUL字符(它的N个字符串有问题),所以不需要使用'vector'。这个问题(你解决的)是'getline'不能处理NUL,另外如果换行符被加密,'getline'将无法找到它们,所以你需要使用二进制读取。 –

+0

这工作正常,但我需要以可读的方式加密“你好”。我的意思是,我需要它像\ xe7 \ xfb \ xe0 \ xe0 \ xe7而不是这样:http://i.imgur.com/tne1I7T.png 这可能吗? 非常感谢! – MrWhite

+0

@ChrisDodd你是对的。 'std :: string'有时会终止,例如当看到“abc \ 0123”时,我通常会在涉及零时远离它。但在这种情况下,它应该没问题。我将编辑答案来显示只是'std :: string' –

1

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

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

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

还要注意,你是与密码的终止nul字节异或。你有意这么做吗?

+0

我全力支持糟糕的答案 - 但帮助我改进;告诉我*我的答案是什么*不好。 –

+0

是的,它包含这些字符。对不起,我不明白你的意思是“处理所有的反斜杠转义符,然后喂它去解码”。你能更具体吗?非常感谢您的帮助! – MrWhite

+0

\ xe7是用十六进制值E7表示* single *字符的常用方法。 (根据你的字符集,这很可能是单个字符'ç')。如果你想存储(加密的)可读文本,我建议删除\ x,并让文件包含诸如“e7fbe0e0e7” –