C++异或加密

XOR encryption with c++

我已经实现了一种相当简单的方法来将字符串加密和解密到文件中,然后再返回。 我使用的方法如下所示:

string encrypt(string msg, string key) {
    string tmp(key);
    while (key.size() < msg.size()) key += tmp;
    for (std::string::size_type i = 0; i < msg.size(); ++i) msg[i] ^= key[i];
    return msg;
}

string decrypt(string msg, string key) {
    return encrypt(msg, key);
}

然而,我使用的一些键不是很有用。该字符串被正确加密并写入文件。但是当我尝试解密所有内容时(将文件加载到字符串中,解密,写回另一个文件)新文件明显更小并且不包含存储在其中的全部信息。

到目前为止我试过的键是:

string crypt = "abc";                           //works kinda well
string crypt = "_H84M!-juJHFXGT01X1*G6a$gEv";   //doesnt work
string crypt = "H84MjuJHFXGT01X1G6agEv";        //doesnt work either

我希望你能帮助我并给我任何关于如何选择可用密钥的建议。

文件处理代码:

ofstream temp;
temp.open("temp", ios::in | ios::trunc);
temp << encrypt(buffer, crypt);
temp.close();


ifstream in(file);
string content((std::istreambuf_iterator<char>(in))                (std::istreambuf_iterator<char>()));
ofstream plain;
plain.open(newfile, ios::in | ios::trunc);
plain << decrypt(content, crypt);
plain.close();

因为你的加密字符串中有二进制数据,你应该使用未格式化的 write 方法而不是 operator<<:

ofstream os(...);
std::string encrypted = ...;
os.write( encrypted.data(), encrypted.size() );

请注意,如果您需要在一个文件中使用多个加密字符串,您可能希望在实际数据之前写入数据大小。然后你用 istream::read():

读取数据大小和数据
void write( std::ostream &out, const std::string &encrypted )
{
    size_t length = encrypted.size(); 
    of.write( &length, sizeof( length ) );
    of.write( encryped.data(), length );
}

std::string read( std::istream &in )
{
     size_t length = 0;
     in.read( &length, sizeof( length ) );
     std::string str( length );
     in.read( &str[0], length );
     return str;
}

注意 2:将加密数据存储在 std::vector<char> 中而不是 std::string 中可能是个好主意,这将防止许多问题 - 您将无法使用隐式假定的许多函数该字符串以 null 结尾。

我刚刚写了一个完整的、最小的、有效的例子。

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

static std::string str_xor(const std::string &data, const std::string &key) {
  std::string result(data.size(), '[=10=]');

  for (std::size_t i = 0, i < data.size(); i++) {
    result[i] = data[i] ^ key[i % key.size()];
  }
  return result;
}

int main(int argc, char **argv) {
  if (argc != 3) {
    std::cerr << "usage: xor <datafile> <keyfile>\n";
    return 1;
  }

  std::ifstream data_in(argv[1]);
  std::string data(
    (std::istreambuf_iterator<char>(data_in)),
    (std::istreambuf_iterator<char>()));
  data_in.close();

  std::ifstream key_in(argv[2]);
  std::string key(
    (std::istreambuf_iterator<char>(key_in)),
    (std::istreambuf_iterator<char>()));
  key_in.close();

  std::string result = str_xor(data, key);

  std::ofstream data_out(argv[1]);
  data_out << result;
  data_out.close();

  return 0;
}

它仍然缺少对文件的错误检查,以防找不到它们。但是如果你将两个现有文件的名称传递给它,它就像一个魅力,使用第二个文件作为密钥加密第一个文件。

警告:由于 https://codereview.stackexchange.com/a/140366.

中给出的充分理由,请勿在实践中使用此程序

好的,您的所有回答和评论都为我指明了正确的方向,但并没有直接在我的程序中起作用。

首先,我按照Slava建议的方式修改了加密算法。其次,我切换了文件处理新方法获取加密文件的整个长度,并通过 char 数组强制每个字符转换为新字符串。我知道这不太好,但我可以将整个代码保留为字符串类型。

所以我想到了以下内容:

ifstream in(file, ios::binary);
in.seekg(0, ios::end);              // go to the end
int length = in.tellg();            // report location (this is the length)
in.seekg(0, ios::beg);              // go back to the beginning
char* content = new char[length];   // allocate memory for a buffer of appropriate dimension
in.read(content, length);           // read the whole file into the buffer
string content2 = "";
for (int i = 0; i < length; i++) con31 += con3[i];  //append to string character by character
ofstream plain;
plain.open(newfile, ios::in | ios::trunc);
plain << decrypt(content2, crypt);
plain.close();

这对我来说效果很好。我希望我没有犯一些严重的错误。