用c++进行异或加密

XOR encryption with c++

本文关键字:加密 c++      更新时间:2023-10-16

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

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,这将防止许多问题-你将无法使用许多函数,隐式地假设字符串是空终止。

我刚刚写了一个完整的,最小的,工作的例子。

#include <fstream>
#include <iostream>
#include <string>
static std::string str_xor(const std::string &data, const std::string &key) {
  std::string result(data.size(), '');
  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();

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