我已经实现了一种相当简单的方法来加密和解密字符串到文件然后再返回。 我使用的方法如下:
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();
答案 0 :(得分:2)
由于加密字符串中包含二进制数据,因此应使用无格式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结尾。
答案 1 :(得分:2)
我刚写了一个完整的,最小的,有效的例子。
#include <fstream>
#include <iostream>
#include <string>
static std::string str_xor(const std::string &data, const std::string &key) {
std::string result(data.size(), '\0');
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中给出了很好的理由,不要在实践中使用这个程序。
答案 2 :(得分:1)
好的,你所有的答案和评论都指出了我正确的方向,但没有直接在我的计划中工作。
首先,我按照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();
这对我来说效果很好。我希望我没有犯一些重大错误。